<?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: Akash Gupta</title>
    <description>The latest articles on DEV Community by Akash Gupta (@akashguptasky).</description>
    <link>https://dev.to/akashguptasky</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%2F3862670%2Fb91ff3f8-1914-4ef4-8653-2262215a9a56.jpg</url>
      <title>DEV Community: Akash Gupta</title>
      <link>https://dev.to/akashguptasky</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/akashguptasky"/>
    <language>en</language>
    <item>
      <title>How to Actually Prepare for a Backend Developer Interview in 2026</title>
      <dc:creator>Akash Gupta</dc:creator>
      <pubDate>Sun, 20 Sep 2026 11:33:08 +0000</pubDate>
      <link>https://dev.to/akashguptasky/how-to-actually-prepare-for-a-backend-developer-interview-in-2026-4h57</link>
      <guid>https://dev.to/akashguptasky/how-to-actually-prepare-for-a-backend-developer-interview-in-2026-4h57</guid>
      <description>&lt;p&gt;Most backend interview prep advice is either "grind 500 LeetCode problems" or "just build projects." Neither alone gets you hired. After mentoring freshers into backend roles, here's the &lt;strong&gt;actual&lt;/strong&gt; breakdown of what interviewers test — and how to prepare for each part efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Language + runtime fundamentals (the fastest points to lose)
&lt;/h2&gt;

&lt;p&gt;For Node.js roles, interviewers almost always probe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The event loop&lt;/strong&gt; — phases, the microtask queue, and why &lt;code&gt;process.nextTick&lt;/code&gt; runs before Promises. If you can't explain how Node handles thousands of concurrent connections on a single thread, that's an instant red flag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Async patterns&lt;/strong&gt; — callbacks → Promises → &lt;code&gt;async/await&lt;/code&gt;, and when to use &lt;code&gt;Promise.all&lt;/code&gt; vs sequential &lt;code&gt;await&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;module.exports&lt;/code&gt; vs &lt;code&gt;exports&lt;/code&gt;&lt;/strong&gt;, &lt;code&gt;require&lt;/code&gt; vs &lt;code&gt;import&lt;/code&gt;, and module caching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streams&lt;/strong&gt; and when to use them instead of buffering.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't just memorize definitions — be ready to explain the &lt;em&gt;why&lt;/em&gt;. I keep a growing set of these Q&amp;amp;As here, open-source:&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://github.com/AS-Backend-Institute/backend-interview-questions" rel="noopener noreferrer"&gt;Backend Developer Interview Questions (GitHub)&lt;/a&gt;&lt;/strong&gt; — Node, Express, MongoDB, MySQL, Redis, System Design &amp;amp; DSA, with clear answers.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Databases — the part freshers underprepare
&lt;/h2&gt;

&lt;p&gt;You'll get questions on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Indexing&lt;/strong&gt; (and why a missing index kills performance at scale)&lt;/li&gt;
&lt;li&gt;SQL &lt;strong&gt;joins&lt;/strong&gt;, normalization, transactions &amp;amp; ACID&lt;/li&gt;
&lt;li&gt;MongoDB &lt;strong&gt;schema design&lt;/strong&gt; (embed vs reference) and the &lt;strong&gt;aggregation pipeline&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis&lt;/strong&gt; for caching, sessions, and rate limiting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Know &lt;em&gt;when&lt;/em&gt; to reach for SQL vs NoSQL vs a cache — that decision-making impresses more than syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. APIs, auth &amp;amp; HTTP
&lt;/h2&gt;

&lt;p&gt;Be crisp on REST design, and &lt;strong&gt;know your status codes cold&lt;/strong&gt; — &lt;code&gt;401 vs 403&lt;/code&gt;, &lt;code&gt;400 vs 422&lt;/code&gt;, &lt;code&gt;502 vs 504&lt;/code&gt; come up constantly, both in interviews and real debugging. I put together a full reference with causes + fixes here:&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://asbackendinstitute.com/http-status-codes" rel="noopener noreferrer"&gt;HTTP Status Codes — meaning, causes &amp;amp; how to fix&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Also nail &lt;strong&gt;JWT auth&lt;/strong&gt;: how the token is signed, why it's stateless, and access vs refresh tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. DSA — enough, not endless
&lt;/h2&gt;

&lt;p&gt;You don't need 500 problems. You need the &lt;strong&gt;patterns&lt;/strong&gt;: hashing, two pointers, sliding window, recursion, trees, and basic graphs — plus always stating time/space complexity out loud.&lt;/p&gt;

&lt;p&gt;A focused, curated sheet beats random grinding. This free one is organized by topic + a 12-week plan with progress tracking:&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://asbackendinstitute.com/dsa-sheet" rel="noopener noreferrer"&gt;Backend-focused DSA Sheet&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. System design basics (yes, even for freshers)
&lt;/h2&gt;

&lt;p&gt;At minimum: horizontal vs vertical scaling, load balancers, caching strategy, and moving heavy work to a &lt;strong&gt;queue&lt;/strong&gt; (BullMQ/RabbitMQ/Kafka). You won't design Twitter, but you should reason about "how would this handle 10x traffic?"&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Mock interviews &amp;gt; re-reading notes
&lt;/h2&gt;

&lt;p&gt;The single highest-ROI step. Practicing out loud exposes the gaps that silent revision hides. Do mock interviews with a peer, a mentor, or even AI — then iterate.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple 6-week plan
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Weeks&lt;/th&gt;
&lt;th&gt;Focus&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1–2&lt;/td&gt;
&lt;td&gt;Node.js + JS fundamentals + async&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Databases (SQL + Mongo + Redis)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;APIs, auth, HTTP, system design basics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;DSA patterns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Mock interviews + revise weak spots&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you want a structured path from basics to job-ready (in English + Hindi), the full &lt;strong&gt;&lt;a href="https://asbackendinstitute.com/roadmap" rel="noopener noreferrer"&gt;backend developer roadmap&lt;/a&gt;&lt;/strong&gt; is free too.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Interviewers test fundamentals → databases → APIs/HTTP → DSA patterns → system design → communication. Prepare each deliberately, practice out loud, and use curated resources instead of grinding blindly.&lt;/p&gt;

&lt;p&gt;What's the toughest backend interview question you've faced? Drop it in the comments 👇&lt;/p&gt;

</description>
      <category>backend</category>
      <category>node</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>7 Node.js Mistakes That Are Quietly Killing Your Backend</title>
      <dc:creator>Akash Gupta</dc:creator>
      <pubDate>Fri, 11 Sep 2026 14:39:48 +0000</pubDate>
      <link>https://dev.to/akashguptasky/7-nodejs-mistakes-that-are-quietly-killing-your-backend-1pep</link>
      <guid>https://dev.to/akashguptasky/7-nodejs-mistakes-that-are-quietly-killing-your-backend-1pep</guid>
      <description>&lt;h1&gt;
  
  
  7 Node.js Mistakes That Are Quietly Killing Your Backend
&lt;/h1&gt;

&lt;p&gt;Your API works. It passes the demo. Then it hits real traffic — and everything slows to a crawl, memory balloons, and one bad request takes the whole thing down.&lt;/p&gt;

&lt;p&gt;Most of the time it's not a hard bug. It's one of these seven quiet mistakes almost every backend developer makes early on. Fix them and your Node.js backend gets faster, safer, and far harder to knock over.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Blocking the event loop
&lt;/h2&gt;

&lt;p&gt;Node is single-threaded for your code. One synchronous, heavy operation freezes &lt;em&gt;every&lt;/em&gt; request, not just the current one.&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;// ❌ blocks everyone while it runs&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pbkdf2Sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha512&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ async version keeps the loop free&lt;/span&gt;
&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pbkdf2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha512&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;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hash&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="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rule of thumb: if a function ends in &lt;code&gt;Sync&lt;/code&gt;, ask what it's blocking. &lt;code&gt;JSON.parse&lt;/code&gt; on a huge payload, big loops, synchronous file reads — same danger.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Not handling promise rejections
&lt;/h2&gt;

&lt;p&gt;An unhandled rejection can crash the whole process in modern Node.&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;// ❌ if this throws, nothing catches it&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="o"&gt;=&amp;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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ wrap async handlers so errors reach your error middleware&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wrap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="o"&gt;=&amp;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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;user&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;
  
  
  3. No database indexes
&lt;/h2&gt;

&lt;p&gt;Your query is fast on 100 rows and dies on 100,000. Without an index, the database scans every single document.&lt;/p&gt;

&lt;p&gt;If a query filters or sorts on a field, that field almost always needs an index. One line often turns a 900ms query into a 3ms one. Check your slow queries &lt;em&gt;before&lt;/em&gt; users find them for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Trusting user input
&lt;/h2&gt;

&lt;p&gt;Every value from the client is hostile until proven otherwise. Unvalidated input is how you get injection, crashes, and garbage in your database.&lt;/p&gt;

&lt;p&gt;Validate the shape and type of every request body and query param at the edge (a schema validator makes this one line per route). Never build a database query by string-concatenating user input.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Leaking secrets and stack traces
&lt;/h2&gt;

&lt;p&gt;Two classics: committing a &lt;code&gt;.env&lt;/code&gt; file, and sending raw error objects to the client.&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;// ❌ hands attackers your stack trace, file paths, and query internals&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&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="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ log the detail, return something safe&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;// or your error tracker&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&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="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Something went wrong&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;p&gt;Keep secrets in environment variables, never in the repo. Add &lt;code&gt;.env&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; your first commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. No timeouts on outbound calls
&lt;/h2&gt;

&lt;p&gt;Calling another API or service with no timeout means one slow dependency can hang your requests forever and pile up until you run out of connections.&lt;/p&gt;

&lt;p&gt;Always set a timeout on outbound HTTP calls and database operations. Fail fast, return a clear error, and your backend stays responsive even when something downstream is having a bad day.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Console.log as your only observability
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;console.log&lt;/code&gt; is fine for local dev. In production it tells you nothing when a real user hits a bug at 2 AM and you're asleep.&lt;/p&gt;

&lt;p&gt;Use structured logging and an error tracker that alerts you the moment something breaks — with the stack trace and the request that caused it. The goal: &lt;em&gt;you&lt;/em&gt; find the bug before your users report it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The pattern behind all seven
&lt;/h2&gt;

&lt;p&gt;Every one of these is the same lesson: &lt;strong&gt;code that works in a demo is not code that survives production.&lt;/strong&gt; The gap between "it runs" and "it holds up under real load, real users, and real attackers" is exactly what separates a hobby project from a hireable backend developer.&lt;/p&gt;

&lt;p&gt;None of this is advanced. It's just rarely taught in order — which is why so many devs learn it the painful way, in production.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I run &lt;a href="https://asbackendinstitute.com" rel="noopener noreferrer"&gt;AS Backend Institute&lt;/a&gt;, where we teach backend and full-stack development the way it actually works in production — not just tutorials that stop at "hello world." If you want a structured path, &lt;a href="https://asbackendinstitute.com" rel="noopener noreferrer"&gt;start here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If this saved you one 2 AM incident, share it with a developer who's still doing &lt;code&gt;console.log&lt;/code&gt; in production. 🙂&lt;/em&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Nobody Gets Hired for Knowing Node.js. Here's What Actually Does.</title>
      <dc:creator>Akash Gupta</dc:creator>
      <pubDate>Mon, 07 Sep 2026 20:17:38 +0000</pubDate>
      <link>https://dev.to/akashguptasky/nobody-gets-hired-for-knowing-nodejs-heres-what-actually-does-5hif</link>
      <guid>https://dev.to/akashguptasky/nobody-gets-hired-for-knowing-nodejs-heres-what-actually-does-5hif</guid>
      <description>&lt;p&gt;Every week I talk to developers who can build a REST API in their sleep, have "MERN stack" on their résumé, and &lt;em&gt;still&lt;/em&gt; can't get past the first interview round.&lt;/p&gt;

&lt;p&gt;And every week I watch someone with &lt;em&gt;worse&lt;/em&gt; raw coding skills get the offer.&lt;/p&gt;

&lt;p&gt;After years of mentoring backend developers and watching who gets hired vs. who gets ghosted, I've stopped believing the thing everyone repeats online: &lt;em&gt;"just learn Node.js and build projects."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That advice is not wrong. It's just &lt;strong&gt;not enough&lt;/strong&gt; — and nobody tells you the rest. Here's the rest.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Companies don't hire "Node.js developers." They hire problem-removers.
&lt;/h2&gt;

&lt;p&gt;Your framework is a detail. What a team actually pays for is: &lt;em&gt;"when something breaks at 2 AM, can this person find it and fix it without panicking?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Knowing Express routing is table stakes. Knowing &lt;strong&gt;why&lt;/strong&gt; a request is slow, &lt;strong&gt;where&lt;/strong&gt; a memory leak hides, and &lt;strong&gt;how&lt;/strong&gt; to read a stack trace under pressure — that's the skill that survives interviews. Learn to debug, not just to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Your project folder is not a portfolio. Your decisions are.
&lt;/h2&gt;

&lt;p&gt;"I built a food-delivery clone" means nothing. Everyone built the clone.&lt;/p&gt;

&lt;p&gt;What makes an interviewer lean in: &lt;em&gt;"I chose a queue here because the emails were blocking the request. I added an index after the query took 900ms. I cached this because it was hit 10,000 times an hour."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Same project. The difference is you can &lt;strong&gt;explain the trade-offs&lt;/strong&gt;. Interviewers hire the person who made choices, not the person who followed a tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. You will be rejected for how you talk about code, not how you write it.
&lt;/h2&gt;

&lt;p&gt;Most rejections after a decent coding round are communication rejections. The candidate solved it — but couldn't say &lt;em&gt;why&lt;/em&gt;, froze when asked "what if the input is 10x bigger," or went silent instead of thinking out loud.&lt;/p&gt;

&lt;p&gt;Practice narrating your thinking. Out loud. To a wall if you have to. The job is 30% typing and 70% explaining what you typed to other humans.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Fundamentals beat frameworks. Every single time.
&lt;/h2&gt;

&lt;p&gt;Frameworks change. Fundamentals compound.&lt;/p&gt;

&lt;p&gt;If you understand how HTTP actually works, what an event loop is doing, why databases use indexes, and what happens between "user clicks button" and "row saved in DB" — you can pick up &lt;em&gt;any&lt;/em&gt; framework in a weekend. The reverse is not true. A dev who only knows the framework is one version bump away from being lost.&lt;/p&gt;

&lt;p&gt;Spend 70% of your energy on the things that don't have a version number.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. "Full-stack" without depth is a red flag, not a feature.
&lt;/h2&gt;

&lt;p&gt;Listing React, Node, Mongo, Docker, Kafka, AWS, and GraphQL on your résumé as a fresher doesn't signal range. It signals that you touched each for a weekend.&lt;/p&gt;

&lt;p&gt;Pick &lt;strong&gt;one&lt;/strong&gt; thing you can go three questions deep on. Real interviewers don't ask "do you know X." They ask "okay, and then what happens under the hood?" — three times. Depth in one area beats a buzzword salad in ten.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Consistency quietly beats talent.
&lt;/h2&gt;

&lt;p&gt;The developers who make it aren't the smartest ones I've met. They're the ones who showed up daily for six months while the "talented" ones did a burst for two weeks and quit.&lt;/p&gt;

&lt;p&gt;A small amount of focused practice every day — reading real code, solving one real problem, shipping something tiny — compounds into a level that looks like genius from the outside. It's not genius. It's just attendance.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Aim at a job, not at "learning to code."
&lt;/h2&gt;

&lt;p&gt;"Learning backend development" is infinite. "Being ready for a backend interview in six months" is a plan.&lt;/p&gt;

&lt;p&gt;Reverse-engineer it: look at 20 real job descriptions for the role you want. List every skill that appears more than five times. &lt;strong&gt;That&lt;/strong&gt; is your syllabus — not a random 40-hour YouTube playlist. Learn what the market is actually paying for, in the order it pays for it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The uncomfortable summary
&lt;/h2&gt;

&lt;p&gt;You don't get hired for knowing Node.js. You get hired for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;being able to &lt;strong&gt;debug&lt;/strong&gt; under pressure,&lt;/li&gt;
&lt;li&gt;being able to &lt;strong&gt;explain your decisions&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;having &lt;strong&gt;depth&lt;/strong&gt; in fundamentals,&lt;/li&gt;
&lt;li&gt;and &lt;strong&gt;showing up consistently&lt;/strong&gt; long enough to get good.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of that is on a certificate. All of it is learnable — but only if someone tells you it's what actually matters. Now someone has.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I run &lt;a href="https://asbackendinstitute.com" rel="noopener noreferrer"&gt;AS Backend Institute&lt;/a&gt;, where we train developers on exactly this — job-ready backend and full-stack skills built around what companies actually hire for, not a random tutorial list. If you want a structured path instead of guessing, the &lt;a href="https://asbackendinstitute.com" rel="noopener noreferrer"&gt;6-month roadmap is here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Found this useful? Share it with the one friend who keeps saying "I know how to code, why am I not getting hired." They need it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>career</category>
      <category>node</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to Structure a Production-Grade Node.js + Express Backend (2026)</title>
      <dc:creator>Akash Gupta</dc:creator>
      <pubDate>Wed, 02 Sep 2026 19:55:27 +0000</pubDate>
      <link>https://dev.to/akashguptasky/how-to-structure-a-production-grade-nodejs-express-backend-2026-42n0</link>
      <guid>https://dev.to/akashguptasky/how-to-structure-a-production-grade-nodejs-express-backend-2026-42n0</guid>
      <description>&lt;h1&gt;
  
  
  How to Structure a Production-Grade Node.js + Express Backend (2026)
&lt;/h1&gt;

&lt;p&gt;Most Node.js tutorials stop at &lt;code&gt;app.get('/', ...)&lt;/code&gt;. Then you land a real project, the codebase hits 40 files, and everything lives in one 800-line &lt;code&gt;index.js&lt;/code&gt;. Been there.&lt;/p&gt;

&lt;p&gt;After building and reviewing dozens of backends, here's the structure and the handful of decisions that actually keep a Node + Express project maintainable — explained so a beginner can follow, but detailed enough to use at work today.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Layer your app: route → controller → service
&lt;/h2&gt;

&lt;p&gt;The single biggest upgrade you can make is to stop putting logic inside routes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Route&lt;/strong&gt; — only wiring. Which URL maps to which handler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controller&lt;/strong&gt; — reads the request, calls a service, sends the response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service&lt;/strong&gt; — the actual business logic (talks to the DB, other APIs).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// routes/user.routes.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;userController&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../controllers/user.controller.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;

&lt;span class="c1"&gt;// controllers/user.controller.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../services/user.service.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="nx"&gt;next&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;try&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&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="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User not found&lt;/span&gt;&lt;span class="dl"&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;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="c1"&gt;// services/user.service.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../models/User.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findById&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;lean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why it matters: your business logic becomes testable without HTTP, and swapping Express for Fastify later touches only the route/controller layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. A folder structure that scales
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  config/        # env, db connection, third-party clients
  models/        # schemas
  routes/        # URL wiring only
  controllers/   # request/response glue
  services/      # business logic
  middleware/    # auth, validation, error handler
  utils/         # pure helpers
  app.js         # express app (no listen)
  server.js      # starts the server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep &lt;code&gt;app.js&lt;/code&gt; (build the app) separate from &lt;code&gt;server.js&lt;/code&gt; (start it). Your tests can import &lt;code&gt;app&lt;/code&gt; without opening a port.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Centralize config — never read &lt;code&gt;process.env&lt;/code&gt; everywhere
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// config/env.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv/config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mongoUri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MONGO_URI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;jwtSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;nodeEnv&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mongoUri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MONGO_URI is required&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;p&gt;Reading env in one place means a missing variable fails &lt;strong&gt;loudly at startup&lt;/strong&gt;, not silently at 2 AM in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. One error handler to rule them all
&lt;/h2&gt;

&lt;p&gt;Stop writing &lt;code&gt;try/catch&lt;/code&gt; that just &lt;code&gt;res.status(500)&lt;/code&gt;. Funnel everything to a single error middleware.&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;// middleware/error.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errorHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&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="nx"&gt;next&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;500&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;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// log real bugs&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&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="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Something went wrong&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="c1"&gt;// app.js (must be registered LAST)&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errorHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Controllers just &lt;code&gt;next(err)&lt;/code&gt; and move on. Clean and consistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Validate input at the edge
&lt;/h2&gt;

&lt;p&gt;Never trust the request body. Validate before it reaches your service (Zod is great):&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signupSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;schema&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="nx"&gt;req&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="nx"&gt;next&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safeParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&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="na"&gt;errors&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issues&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;
  &lt;span class="nf"&gt;next&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;
  
  
  6. The security basics you can't skip
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;helmet()&lt;/code&gt; for sane HTTP headers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;express-rate-limit&lt;/code&gt; on auth routes&lt;/li&gt;
&lt;li&gt;Hash passwords with &lt;code&gt;bcrypt&lt;/code&gt; (never store plaintext)&lt;/li&gt;
&lt;li&gt;Keep secrets in env, &lt;strong&gt;never&lt;/strong&gt; in the repo (add &lt;code&gt;.env&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Validate + sanitize every input (point 5)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;helmet&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;helmet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;rateLimit&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express-rate-limit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;helmet&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;rateLimit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;windowMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Graceful shutdown (the detail nobody teaches)
&lt;/h2&gt;

&lt;p&gt;When your host restarts the app, finish in-flight requests and close the DB cleanly:&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;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGTERM&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&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="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;A good backend isn't about knowing every library — it's about &lt;strong&gt;separation of concerns, failing loudly, and never trusting input&lt;/strong&gt;. Master these seven and you're already ahead of most juniors.&lt;/p&gt;

&lt;p&gt;If you want a structured path from "first API" to "deployed, production-ready backend" — with Node.js, Express, MongoDB, MySQL and Redis — that's exactly what we teach at &lt;a href="https://asbackendinstitute.com" rel="noopener noreferrer"&gt;AS Backend Institute&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What does your Express folder structure look like? Drop it in the comments 👇&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Written by the team at &lt;a href="https://asbackendinstitute.com" rel="noopener noreferrer"&gt;AS Backend Institute&lt;/a&gt; — a placement-focused backend development course for aspiring developers in India.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>backend</category>
      <category>express</category>
      <category>webdev</category>
    </item>
    <item>
      <title>A stranger's comment rewrote my retention strategy — so I shipped it the same day</title>
      <dc:creator>Akash Gupta</dc:creator>
      <pubDate>Mon, 31 Aug 2026 18:13:30 +0000</pubDate>
      <link>https://dev.to/akashguptasky/a-strangers-comment-rewrote-my-retention-strategy-so-i-shipped-it-the-same-day-46bg</link>
      <guid>https://dev.to/akashguptasky/a-strangers-comment-rewrote-my-retention-strategy-so-i-shipped-it-the-same-day-46bg</guid>
      <description>&lt;p&gt;I'm building a backend-development learning platform solo — the whole thing: Node/Express API, MongoDB, Socket, SQL, live classes, a roadmap, assignments, certificates. Real students, real fees, one developer.&lt;/p&gt;

&lt;p&gt;Last week I posted about it here. The most valuable thing that came out of it wasn't traffic — it was &lt;strong&gt;one comment.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The comment that changed my roadmap
&lt;/h2&gt;

&lt;p&gt;A developer in the comments pushed back on how I was thinking about retention. My instinct was streaks (the Duolingo flame). Their point, paraphrased:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Streaks are fragile. One missed day and streak-based motivation collapses. Track the % of active days vs total days as your internal health metric — and show the user an all-time tally instead. "You've practiced X times" survives a broken streak in a way "streak: 0" never does.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That reframed the whole thing for me. A streak is a &lt;strong&gt;motivator&lt;/strong&gt;, not a &lt;strong&gt;measure&lt;/strong&gt;. The moment it breaks, it demotivates the exact person who needed one more nudge.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I shipped it — the same day
&lt;/h2&gt;

&lt;p&gt;I added a lifetime &lt;strong&gt;"days practiced"&lt;/strong&gt; count next to the streak. It counts the distinct days a student actually did the work, and it never resets — even after a missed day.&lt;/p&gt;

&lt;p&gt;Streak = the visible nudge. "You've shown up 24 times" = the thing that keeps you going after you miss a day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then I realized the bigger lesson
&lt;/h2&gt;

&lt;p&gt;That one comment was worth more than a week of my own planning. So I asked: how do I get more of this from actual users, not just from Dev.to?&lt;/p&gt;

&lt;p&gt;I built an in-app &lt;strong&gt;"Report a bug / feedback"&lt;/strong&gt; button. On the platform, once you're logged in: click your &lt;strong&gt;avatar (top-right) → Report a bug&lt;/strong&gt;, type what broke, and hit send — and it lands in a dashboard I triage every day.&lt;/p&gt;

&lt;p&gt;Try it here: &lt;strong&gt;&lt;a href="https://asbackendinstitute.com" rel="noopener noreferrer"&gt;https://asbackendinstitute.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The bet: &lt;strong&gt;your users' bugs and comments are your real roadmap.&lt;/strong&gt; Make it stupidly easy for them to hand it to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;Building solo doesn't mean building alone. The best product decisions this month didn't come from me — they came from a comment, and (now) from a feedback button. My job is mostly to &lt;strong&gt;listen fast and ship faster.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you've built something people use: what's the one piece of user feedback that changed your product the most?&lt;/p&gt;

&lt;p&gt;— Akash, solo dev, AS Backend Institute&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>webdev</category>
      <category>node</category>
      <category>startup</category>
    </item>
    <item>
      <title>15 Git Commands That Quietly Separate Juniors from Seniors</title>
      <dc:creator>Akash Gupta</dc:creator>
      <pubDate>Fri, 28 Aug 2026 08:00:53 +0000</pubDate>
      <link>https://dev.to/akashguptasky/15-git-commands-that-quietly-separate-juniors-from-seniors-a3m</link>
      <guid>https://dev.to/akashguptasky/15-git-commands-that-quietly-separate-juniors-from-seniors-a3m</guid>
      <description>&lt;p&gt;Everyone knows &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;commit&lt;/code&gt;, &lt;code&gt;push&lt;/code&gt;. That's the entry fee, not the game.&lt;/p&gt;

&lt;p&gt;The developers who move fast — the ones who never lose work, never ship an ugly history, and never panic when a rebase goes sideways — all quietly share the same toolbox. It's not senior "Git magic." It's about 15 commands you can learn in an afternoon and lean on for the rest of your career.&lt;/p&gt;

&lt;p&gt;I teach backend developers over at &lt;a href="https://asbackendinstitute.com" rel="noopener noreferrer"&gt;AS Backend Institute&lt;/a&gt;, and if I had to name one skill that predicts seniority without touching a single line of application code, it's Git fluency. So here are the 15 I actually reach for every week — with the gotchas nobody warns you about.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;code&gt;git switch&lt;/code&gt; and &lt;code&gt;git restore&lt;/code&gt; — stop using &lt;code&gt;checkout&lt;/code&gt; for everything
&lt;/h2&gt;

&lt;p&gt;For years &lt;code&gt;checkout&lt;/code&gt; did two unrelated jobs: switching branches &lt;em&gt;and&lt;/em&gt; throwing away file changes. That overloading caused real accidents. Modern Git split it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git switch main            &lt;span class="c"&gt;# change branch&lt;/span&gt;
git switch &lt;span class="nt"&gt;-c&lt;/span&gt; feature/pay  &lt;span class="c"&gt;# create + switch&lt;/span&gt;
git restore src/app.js     &lt;span class="c"&gt;# discard changes in a file&lt;/span&gt;
git restore &lt;span class="nt"&gt;--staged&lt;/span&gt; x.js  &lt;span class="c"&gt;# unstage, keep the edits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Gotcha:&lt;/strong&gt; &lt;code&gt;git restore &amp;lt;file&amp;gt;&lt;/code&gt; permanently discards uncommitted changes. There's no undo. Reach for it deliberately.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;code&gt;git add -p&lt;/code&gt; — commit like a surgeon
&lt;/h2&gt;

&lt;p&gt;Changed five unrelated things in one file? Don't dump them into one commit. Stage &lt;em&gt;hunks&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git walks you through each change: &lt;code&gt;y&lt;/code&gt; (stage), &lt;code&gt;n&lt;/code&gt; (skip), &lt;code&gt;s&lt;/code&gt; (split further), &lt;code&gt;e&lt;/code&gt; (edit the hunk by hand). This one habit is the difference between a readable history and a "misc fixes" graveyard.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;code&gt;git commit --amend&lt;/code&gt; — fix the last commit, not your dignity
&lt;/h2&gt;

&lt;p&gt;Forgot a file? Typo in the message? Don't add a &lt;code&gt;fix typo&lt;/code&gt; commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add forgotten.js
git commit &lt;span class="nt"&gt;--amend&lt;/span&gt; &lt;span class="nt"&gt;--no-edit&lt;/span&gt;   &lt;span class="c"&gt;# fold it in, keep the message&lt;/span&gt;
git commit &lt;span class="nt"&gt;--amend&lt;/span&gt;             &lt;span class="c"&gt;# ...or edit the message too&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Gotcha:&lt;/strong&gt; amend rewrites the commit (new hash). Fine locally. If it's already pushed, you'll need a force push — see #13.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;code&gt;git commit --fixup&lt;/code&gt; + &lt;code&gt;--autosquash&lt;/code&gt; — amend an &lt;em&gt;old&lt;/em&gt; commit
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;--amend&lt;/code&gt; only fixes the &lt;em&gt;last&lt;/em&gt; commit. To fix one buried three commits back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;--fixup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;              &lt;span class="c"&gt;# a marked "fixup!" commit&lt;/span&gt;
git rebase &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;--autosquash&lt;/span&gt; main        &lt;span class="c"&gt;# Git auto-orders it next to its target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the professional move most people never learn. Your fix lands exactly where it belongs, automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;code&gt;git rebase -i&lt;/code&gt; — the history editor
&lt;/h2&gt;

&lt;p&gt;Interactive rebase lets you reshape recent commits: &lt;code&gt;reword&lt;/code&gt;, &lt;code&gt;squash&lt;/code&gt;, &lt;code&gt;fixup&lt;/code&gt;, &lt;code&gt;drop&lt;/code&gt;, &lt;code&gt;edit&lt;/code&gt;, and reorder — just by editing a list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git rebase &lt;span class="nt"&gt;-i&lt;/span&gt; HEAD~5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Turn &lt;code&gt;add validation&lt;/code&gt; → &lt;code&gt;fix validation&lt;/code&gt; → &lt;code&gt;actually fix it&lt;/code&gt; into one clean &lt;code&gt;Add form validation&lt;/code&gt;. &lt;strong&gt;Rule:&lt;/strong&gt; only rewrite commits nobody else has pulled.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;code&gt;git stash&lt;/code&gt; — park work without committing junk
&lt;/h2&gt;

&lt;p&gt;Production's on fire and your feature half-builds? Stash it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash push &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"wip: checkout flow"&lt;/span&gt;   &lt;span class="c"&gt;# -u also stashes untracked files&lt;/span&gt;
git stash &lt;span class="nt"&gt;-p&lt;/span&gt;                                &lt;span class="c"&gt;# stash only selected hunks&lt;/span&gt;
git stash list
git stash show &lt;span class="nt"&gt;-p&lt;/span&gt; stash@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;
git stash pop                               &lt;span class="c"&gt;# apply + remove&lt;/span&gt;
git stash apply stash@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;                   &lt;span class="c"&gt;# apply, keep in list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Gotcha:&lt;/strong&gt; without &lt;code&gt;-u&lt;/code&gt;, brand-new untracked files stay behind. Always name your stashes — "future you" won't remember what &lt;code&gt;stash@{3}&lt;/code&gt; was.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. &lt;code&gt;git cherry-pick&lt;/code&gt; — grab one commit, not the whole branch
&lt;/h2&gt;

&lt;p&gt;You need &lt;em&gt;one&lt;/em&gt; commit from another branch — a config fix, a hotfix — nothing else:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git cherry-pick &amp;lt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
git cherry-pick &lt;span class="nt"&gt;-x&lt;/span&gt; &amp;lt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;   &lt;span class="c"&gt;# records "cherry picked from…" in the message&lt;/span&gt;
git cherry-pick &lt;span class="nt"&gt;-n&lt;/span&gt; &amp;lt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;   &lt;span class="c"&gt;# apply but don't commit (batch several, then commit)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect for porting a single fix onto a release branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. &lt;code&gt;git bisect&lt;/code&gt; — binary-search the commit that broke it
&lt;/h2&gt;

&lt;p&gt;Bug appeared "sometime in the last 200 commits"? Don't guess. Let Git find it in ~8 steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect start
git bisect bad                 &lt;span class="c"&gt;# current commit is broken&lt;/span&gt;
git bisect good v1.4.0         &lt;span class="c"&gt;# this old one worked&lt;/span&gt;
&lt;span class="c"&gt;# Git checks out the midpoint — you test and mark:&lt;/span&gt;
git bisect good   &lt;span class="c"&gt;# or: git bisect bad&lt;/span&gt;
&lt;span class="c"&gt;# ...repeat until Git names the exact culprit&lt;/span&gt;
git bisect reset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even better, automate it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect run npm &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git runs your test on each midpoint and finds the breaking commit on its own. The first time you see this work, it feels illegal.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. &lt;code&gt;git worktree&lt;/code&gt; — two branches, two folders, one repo
&lt;/h2&gt;

&lt;p&gt;The best-kept secret for context switching. Instead of stashing your feature to fix a prod bug, check the other branch out into a &lt;em&gt;separate folder&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree add ../hotfix main
&lt;span class="c"&gt;# fix, commit, push from ../hotfix — your feature work stays untouched&lt;/span&gt;
git worktree remove ../hotfix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No stashing, no rebuild churn, no lost train of thought.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. &lt;code&gt;git log -S&lt;/code&gt; and &lt;code&gt;git log -L&lt;/code&gt; — detective mode
&lt;/h2&gt;

&lt;p&gt;"When did this line appear? Who deleted this function?"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;-S&lt;/span&gt; &lt;span class="s2"&gt;"calculateTax"&lt;/span&gt; &lt;span class="nt"&gt;--oneline&lt;/span&gt;    &lt;span class="c"&gt;# commits that added/removed that string&lt;/span&gt;
git log &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; :calculateTax:tax.js     &lt;span class="c"&gt;# full history of one function&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "pickaxe" (&lt;code&gt;-S&lt;/code&gt;) has ended more "who wrote this and why" arguments than any meeting ever will.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. &lt;code&gt;git blame -w -C&lt;/code&gt; — line-by-line history, done right
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git blame &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; src/auth.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-w&lt;/code&gt; ignores whitespace-only changes; &lt;code&gt;-C&lt;/code&gt; follows code that was moved or copied — so you blame the &lt;em&gt;real&lt;/em&gt; author, not whoever ran the formatter. Then read the commit for the &lt;em&gt;why&lt;/em&gt;, not to assign blame. 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  12. &lt;code&gt;git reflog&lt;/code&gt; — the undo button for "undo"
&lt;/h2&gt;

&lt;p&gt;Nuked a branch with a bad reset? Git logs almost every move of &lt;code&gt;HEAD&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reflog
&lt;span class="c"&gt;# 821cd77 HEAD@{1}: commit: Add authentication   ← there it is&lt;/span&gt;
git branch rescue 821cd77   &lt;span class="c"&gt;# recover it safely into a new branch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Limit:&lt;/strong&gt; reflog only resurrects things Git already stored (commits, stashes). Work you never committed is gone. Translation: commit early, commit often.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. &lt;code&gt;git reset --soft / --mixed / --hard&lt;/code&gt; (+ safe force push)
&lt;/h2&gt;

&lt;p&gt;One command, three levels of "go back," each answering "what happens to my changes?"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset &lt;span class="nt"&gt;--soft&lt;/span&gt;  HEAD~1   &lt;span class="c"&gt;# undo commit, keep changes STAGED&lt;/span&gt;
git reset &lt;span class="nt"&gt;--mixed&lt;/span&gt; HEAD~1   &lt;span class="c"&gt;# undo commit, keep changes UNSTAGED (default)&lt;/span&gt;
git reset &lt;span class="nt"&gt;--hard&lt;/span&gt;  HEAD~1   &lt;span class="c"&gt;# undo commit, DISCARD changes (danger)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After any history rewrite, push safely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;--force-with-lease&lt;/span&gt;   &lt;span class="c"&gt;# refuses to clobber if someone else pushed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--force-with-lease&lt;/code&gt; over &lt;code&gt;--force&lt;/code&gt;, always. It's the difference between "oops" and "I just deleted my teammate's afternoon."&lt;/p&gt;

&lt;h2&gt;
  
  
  14. &lt;code&gt;git revert&lt;/code&gt; — undo on shared branches without rewriting history
&lt;/h2&gt;

&lt;p&gt;A bad commit is already on &lt;code&gt;main&lt;/code&gt;/&lt;code&gt;develop&lt;/code&gt;. &lt;strong&gt;Do not&lt;/strong&gt; reset + force-push a shared branch. Create an inverse commit instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git revert &amp;lt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;History stays honest: the change happened, it broke things, it was reverted — everyone can see the trail. Rule of thumb: &lt;strong&gt;shared branch → revert; private branch → reset.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  15. &lt;code&gt;git rerere&lt;/code&gt; — Git remembers how you fixed a conflict
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Reuse Recorded Resolution.&lt;/em&gt; Enable it once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; rerere.enabled &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you resolve a conflict, Git records it. Hit the &lt;em&gt;same&lt;/em&gt; conflict again (super common during long rebases) and it replays your resolution automatically. Obscure, underused, borderline magical.&lt;/p&gt;

&lt;p&gt;please checkit out this also: &lt;a href="https://dev.to/akashguptasky/a-strangers-comment-rewrote-my-retention-strategy-so-i-shipped-it-the-same-day-46bg"&gt;a-strangers-comment-rewrote-my-retention-strategy-so-i-shipped-it-the-same-day&lt;/a&gt; &lt;/p&gt;




&lt;h3&gt;
  
  
  The pattern underneath all of these
&lt;/h3&gt;

&lt;p&gt;Notice the theme: most of these exist so you can &lt;strong&gt;keep a clean, honest history&lt;/strong&gt; and &lt;strong&gt;never lose work&lt;/strong&gt;. That's really what Git seniority is — not memorizing flags, but having the reflexes to move fast without breaking things.&lt;/p&gt;

&lt;p&gt;If you're leveling up your backend skills and want more hands-on workflow stuff like this, we publish free guides over at &lt;a href="https://asbackendinstitute.com/blog" rel="noopener noreferrer"&gt;AS Backend Institute&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Which command surprised you? And what's the one intermediate command I left out that you'd fight to keep? Drop it in the comments — I always end up learning something. 👇&lt;/p&gt;

</description>
      <category>git</category>
      <category>programming</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Node.js Event Loop, Explained Simply (with Examples)</title>
      <dc:creator>Akash Gupta</dc:creator>
      <pubDate>Wed, 26 Aug 2026 17:52:09 +0000</pubDate>
      <link>https://dev.to/akashguptasky/the-nodejs-event-loop-explained-simply-with-examples-4n4g</link>
      <guid>https://dev.to/akashguptasky/the-nodejs-event-loop-explained-simply-with-examples-4n4g</guid>
      <description>&lt;p&gt;"Node.js is single-threaded" — you've heard it a hundred times. So how does it handle thousands of requests at once without freezing?&lt;/p&gt;

&lt;p&gt;The answer is the &lt;strong&gt;event loop&lt;/strong&gt;. Once it clicks, a lot of Node "magic" suddenly makes sense. Let's break it down.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-line mental model
&lt;/h2&gt;

&lt;p&gt;Node runs your JavaScript on &lt;strong&gt;one main thread&lt;/strong&gt;, but hands off slow work (file reads, network calls, timers) to the system, and picks up the results later via the &lt;strong&gt;event loop&lt;/strong&gt;. So one thread juggles thousands of connections — it just never sits around waiting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blocking vs non-blocking
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Blocking — nothing else runs until this file is read&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;big.txt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Non-blocking — Node starts the read and moves on&lt;/span&gt;
&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;big.txt&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;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;done reading&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;this prints FIRST&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;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this prints FIRST
done reading
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second version doesn't wait — that's the whole point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The phases (simplified)
&lt;/h2&gt;

&lt;p&gt;Each loop iteration goes through phases, in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Timers&lt;/strong&gt; — &lt;code&gt;setTimeout&lt;/code&gt; / &lt;code&gt;setInterval&lt;/code&gt; callbacks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Poll&lt;/strong&gt; — I/O callbacks (file, network)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check&lt;/strong&gt; — &lt;code&gt;setImmediate&lt;/code&gt; callbacks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Close&lt;/strong&gt; — cleanup callbacks&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And between every phase, Node drains the &lt;strong&gt;microtask queue&lt;/strong&gt; first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Microtasks jump the line
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;process.nextTick()&lt;/code&gt; and resolved &lt;strong&gt;Promises&lt;/strong&gt; are microtasks — they run &lt;em&gt;before&lt;/em&gt; the loop moves to the next phase.&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4&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;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1
4
3   ← Promise (microtask) runs before setTimeout
2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most people guess &lt;code&gt;1 2 4 3&lt;/code&gt;. If you understand why it's &lt;code&gt;1 4 3 2&lt;/code&gt;, you understand the event loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  setTimeout vs setImmediate
&lt;/h2&gt;

&lt;p&gt;Inside an I/O callback, &lt;code&gt;setImmediate&lt;/code&gt; always fires before &lt;code&gt;setTimeout(fn, 0)&lt;/code&gt;:&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;f.txt&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timeout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;setImmediate&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;immediate&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="c1"&gt;// → immediate, then timeout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The one rule that keeps Node fast
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Never block the event loop.&lt;/strong&gt; A heavy CPU task (huge loop, sync crypto, giant JSON parse) freezes &lt;em&gt;everything&lt;/em&gt;, because it hogs the single thread. Offload it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;worker_threads&lt;/code&gt; for CPU-heavy work&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;cluster&lt;/code&gt; module to use all cores&lt;/li&gt;
&lt;li&gt;a queue/microservice for big jobs&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;One JS thread + the event loop = non-blocking I/O&lt;/li&gt;
&lt;li&gt;Microtasks (nextTick, Promises) run before the next phase&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setImmediate&lt;/code&gt; beats &lt;code&gt;setTimeout(0)&lt;/code&gt; inside I/O&lt;/li&gt;
&lt;li&gt;Don't block the loop with heavy CPU work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The event loop is one of the most common interview questions too — if you want the full set, I put together a &lt;strong&gt;64-question Node.js interview guide&lt;/strong&gt; here: &lt;a href="https://asbackendinstitute.com/blog/nodejs-interview-questions/top-60-nodejs-interview-questions" rel="noopener noreferrer"&gt;https://asbackendinstitute.com/blog/nodejs-interview-questions/top-60-nodejs-interview-questions&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I teach hands-on backend development (Node.js, Express, MongoDB, Redis) at &lt;a href="https://asbackendinstitute.com" rel="noopener noreferrer"&gt;AS Backend Institute&lt;/a&gt;. More practical guides like this if you're learning backend. 🚀&lt;/em&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>15 Node.js Interview Questions You Should Be Able to Answer (2026)</title>
      <dc:creator>Akash Gupta</dc:creator>
      <pubDate>Mon, 24 Aug 2026 19:35:15 +0000</pubDate>
      <link>https://dev.to/akashguptasky/15-nodejs-interview-questions-you-should-be-able-to-answer-2026-5aeg</link>
      <guid>https://dev.to/akashguptasky/15-nodejs-interview-questions-you-should-be-able-to-answer-2026-5aeg</guid>
      <description>&lt;p&gt;Prepping for a Node.js interview? Here are 15 questions that come up again and again — with short, to-the-point answers. If you can explain these clearly, you're in good shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basics
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. What is Node.js?&lt;/strong&gt;&lt;br&gt;
A runtime to run JavaScript outside the browser (built on V8). It's event-driven and non-blocking — great for I/O-heavy apps like APIs and real-time servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Is Node.js single-threaded?&lt;/strong&gt;&lt;br&gt;
Your JS runs on one main thread, but Node offloads heavy I/O to libuv's background thread pool. So it feels single-threaded but uses multiple threads under the hood.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. CommonJS vs ES Modules?&lt;/strong&gt;&lt;br&gt;
CommonJS uses &lt;code&gt;require&lt;/code&gt;/&lt;code&gt;module.exports&lt;/code&gt; (synchronous, classic). ES Modules use &lt;code&gt;import&lt;/code&gt;/&lt;code&gt;export&lt;/code&gt; (modern standard, async, tree-shakeable). Enable ESM via &lt;code&gt;"type":"module"&lt;/code&gt; or &lt;code&gt;.mjs&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Event loop &amp;amp; async
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;4. What is the event loop?&lt;/strong&gt;&lt;br&gt;
The mechanism that lets single-threaded Node handle many operations at once — it runs callbacks for completed async tasks (timers, I/O) when the call stack is empty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. setTimeout vs setImmediate?&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;setImmediate&lt;/code&gt; runs in the "check" phase; &lt;code&gt;setTimeout(fn,0)&lt;/code&gt; in the timers phase. Inside an I/O callback, &lt;code&gt;setImmediate&lt;/code&gt; always fires first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. What is async/await?&lt;/strong&gt;&lt;br&gt;
Syntactic sugar over Promises so async code reads like sync code. An &lt;code&gt;async&lt;/code&gt; function returns a Promise; &lt;code&gt;await&lt;/code&gt; pauses until it settles. Handle errors with try/catch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Promise.all vs allSettled vs race vs any?&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;all&lt;/code&gt;: rejects on first failure. &lt;code&gt;allSettled&lt;/code&gt;: waits for all, reports each. &lt;code&gt;race&lt;/code&gt;: first to settle wins. &lt;code&gt;any&lt;/code&gt;: first success wins, rejects only if all fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. How do you handle CPU-intensive tasks?&lt;/strong&gt;&lt;br&gt;
Offload them — &lt;code&gt;worker_threads&lt;/code&gt; for parallel CPU work, child processes, or the &lt;code&gt;cluster&lt;/code&gt; module to use all cores. Never block the single JS thread.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modules &amp;amp; core
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;9. What are streams?&lt;/strong&gt;&lt;br&gt;
They process data in chunks instead of loading it all into memory — ideal for large files/network. Types: Readable, Writable, Duplex, Transform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10. How does require() caching work?&lt;/strong&gt;&lt;br&gt;
The first &lt;code&gt;require()&lt;/code&gt; runs the module and caches its exports. Later requires return the cache — so top-level module code runs only once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Express &amp;amp; REST
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;11. What is middleware?&lt;/strong&gt;&lt;br&gt;
A function with &lt;code&gt;(req, res, next)&lt;/code&gt; that runs during the request-response cycle. It can read/modify req/res, end the response, or call &lt;code&gt;next()&lt;/code&gt; to pass control on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;12. What are the key REST principles?&lt;/strong&gt;&lt;br&gt;
Resources identified by URLs (nouns), standard HTTP methods (verbs), stateless requests, and meaningful status codes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auth &amp;amp; security
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;13. How does JWT auth work?&lt;/strong&gt;&lt;br&gt;
On login the server signs a token (header.payload.signature). The client sends it on each request; the server verifies the signature. The payload is only Base64-encoded — never put secrets in it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;14. How should you store passwords?&lt;/strong&gt;&lt;br&gt;
Never plain text. Hash with a slow, salted algorithm like bcrypt, and compare with &lt;code&gt;bcrypt.compare&lt;/code&gt; on login — you never decrypt the stored hash.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;15. How do you scale a Node app?&lt;/strong&gt;&lt;br&gt;
Use the &lt;code&gt;cluster&lt;/code&gt; module (or PM2) to use all CPU cores, cache with Redis, add DB indexes, avoid blocking the event loop, and paginate large responses.&lt;/p&gt;




&lt;p&gt;Want the full set? I wrote a &lt;strong&gt;complete 64-question guide (beginner → advanced, with English/Hinglish)&lt;/strong&gt; here:&lt;br&gt;
👉 &lt;a href="https://asbackendinstitute.com/blog/nodejs-interview-questions/top-60-nodejs-interview-questions" rel="noopener noreferrer"&gt;https://asbackendinstitute.com/blog/nodejs-interview-questions/top-60-nodejs-interview-questions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What question do you always get asked in Node interviews? Drop it below 👇&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>interview</category>
    </item>
    <item>
      <title>JWT Authentication in Node.js: A Practical Guide (with Express)</title>
      <dc:creator>Akash Gupta</dc:creator>
      <pubDate>Mon, 24 Aug 2026 12:42:21 +0000</pubDate>
      <link>https://dev.to/akashguptasky/jwt-authentication-in-nodejs-a-practical-guide-with-express-2341</link>
      <guid>https://dev.to/akashguptasky/jwt-authentication-in-nodejs-a-practical-guide-with-express-2341</guid>
      <description>&lt;p&gt;Ever logged into an app, closed the tab, come back, and you're &lt;em&gt;still&lt;/em&gt; logged in — no password needed? That's almost always &lt;strong&gt;JWT&lt;/strong&gt; doing its job behind the scenes.&lt;/p&gt;

&lt;p&gt;JWT (JSON Web Token) is one of the most common ways to handle authentication in modern backends. But a lot of developers use it without really understanding what's happening — and that's exactly where security bugs sneak in.&lt;/p&gt;

&lt;p&gt;Let's fix that. By the end of this post you'll know what a JWT actually is, how to use it in a Node.js + Express app, and the mistakes that quietly break real apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a JWT, really?
&lt;/h2&gt;

&lt;p&gt;A JWT is just a &lt;strong&gt;string with three parts&lt;/strong&gt;, separated by dots:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xxxxx.yyyyy.zzzzz
   │      │      │
 header payload signature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Header&lt;/strong&gt; — says which algorithm signed the token (e.g. &lt;code&gt;HS256&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload&lt;/strong&gt; — the actual data (like &lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;role&lt;/code&gt;, and an expiry time). This is &lt;strong&gt;not encrypted&lt;/strong&gt; — it's just Base64-encoded. Anyone can read it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signature&lt;/strong&gt; — a cryptographic stamp created using a &lt;strong&gt;secret&lt;/strong&gt; only your server knows. This is what stops people from faking tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Want to see this for yourself? Paste any token into a free &lt;a href="https://asbackendinstitute.com/tools/jwt-decoder" rel="noopener noreferrer"&gt;JWT decoder&lt;/a&gt; and you'll instantly see the header and payload. Notice you can read everything &lt;em&gt;without&lt;/em&gt; the secret — that's the key lesson: &lt;strong&gt;never put passwords or sensitive data in a JWT payload.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a token (login)
&lt;/h2&gt;

&lt;p&gt;Install the library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;jsonwebtoken
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a user logs in successfully, sign a token:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// On successful login:&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="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;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;role&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;role&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;   &lt;span class="c1"&gt;// payload&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                    &lt;span class="c1"&gt;// secret (keep it in .env!)&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;7d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;                        &lt;span class="c1"&gt;// auto-expiry&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;token&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things to notice:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep the payload &lt;strong&gt;small&lt;/strong&gt; — just an id and role, not the whole user object.&lt;/li&gt;
&lt;li&gt;The secret lives in an environment variable, &lt;strong&gt;never&lt;/strong&gt; hardcoded.&lt;/li&gt;
&lt;li&gt;Always set &lt;code&gt;expiresIn&lt;/code&gt;. A token that never expires is a token that can be stolen forever.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Verifying a token (protecting routes)
&lt;/h2&gt;

&lt;p&gt;Now create a middleware that checks the token on every protected request:&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="nx"&gt;next&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;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorization&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&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;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bearer &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;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&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="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No token provided&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="k"&gt;try&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;decoded&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;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;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt;          &lt;span class="c1"&gt;// { userId, role, iat, exp }&lt;/span&gt;
    &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&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="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid or expired token&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use it on any route you want to protect:&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="o"&gt;=&amp;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="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&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;userId&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;That's the whole core loop: &lt;strong&gt;sign on login, verify on every request.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The mistakes that break real apps
&lt;/h2&gt;

&lt;p&gt;These are the ones I see again and again:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Trusting the payload without verifying.&lt;/strong&gt; Decoding a token (reading it) is &lt;em&gt;not&lt;/em&gt; the same as verifying it. Always use &lt;code&gt;jwt.verify()&lt;/code&gt;, never just decode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A weak or leaked secret.&lt;/strong&gt; If your secret is &lt;code&gt;secret123&lt;/code&gt; or committed to GitHub, anyone can forge valid tokens. Use a long random string.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No expiry.&lt;/strong&gt; Always set &lt;code&gt;expiresIn&lt;/code&gt;. Pair short-lived access tokens with a longer refresh token for a better experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storing the token in &lt;code&gt;localStorage&lt;/code&gt; carelessly.&lt;/strong&gt; It's vulnerable to XSS. For sensitive apps, an &lt;code&gt;httpOnly&lt;/code&gt; cookie is safer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Putting secrets in the payload.&lt;/strong&gt; Remember — the payload is readable by anyone. No passwords, no card numbers.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Debugging tip
&lt;/h2&gt;

&lt;p&gt;When something "just doesn't work," the fastest fix is to actually &lt;em&gt;look&lt;/em&gt; at the token. Drop it into a &lt;a href="https://asbackendinstitute.com/tools/jwt-decoder" rel="noopener noreferrer"&gt;JWT decoder&lt;/a&gt; and check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the &lt;code&gt;exp&lt;/code&gt; (expiry) in the past? → token expired.&lt;/li&gt;
&lt;li&gt;Is the payload what you expect? → maybe you signed the wrong data.&lt;/li&gt;
&lt;li&gt;Wrong &lt;code&gt;alg&lt;/code&gt; in the header? → algorithm mismatch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;90% of JWT bugs become obvious the moment you see the decoded token.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;JWT isn't magic — it's a signed string that says "this user is who they claim to be, and here's proof my server made it." Get the basics right (small payload, strong secret, always expire, always verify) and you've covered most of what breaks in production.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I teach hands-on backend development (Node.js, Express, MongoDB, Redis) at &lt;a href="https://asbackendinstitute.com" rel="noopener noreferrer"&gt;AS Backend Institute&lt;/a&gt;. If you're learning backend and want more practical guides like this, come say hi. 🚀&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>node</category>
      <category>security</category>
    </item>
    <item>
      <title>I built a full backend-learning platform solo — here's what I shipped (and what broke along the way)</title>
      <dc:creator>Akash Gupta</dc:creator>
      <pubDate>Sat, 08 Aug 2026 22:15:45 +0000</pubDate>
      <link>https://dev.to/akashguptasky/i-built-a-full-backend-learning-platform-solo-heres-what-i-shipped-and-what-broke-along-the-way-990</link>
      <guid>https://dev.to/akashguptasky/i-built-a-full-backend-learning-platform-solo-heres-what-i-shipped-and-what-broke-along-the-way-990</guid>
      <description>&lt;p&gt;A few months ago I got tired of the same problem: you finish a "backend course," feel great for a day, then realize you still can't build anything real or pass an interview.&lt;/p&gt;

&lt;p&gt;So I started building the thing I wish I'd had when I began. Today it's finally live: &lt;strong&gt;&lt;a href="https://asbackendinstitute.com" rel="noopener noreferrer"&gt;https://asbackendinstitute.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Posting it here because dev.to is where I learned a ton — I'd genuinely love your feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;Most resources hand you videos and call it a day. The gap between "I watched a tutorial" and "I can actually build and get hired" is where people give up. I wanted the whole thing to be hands-on and job-focused.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's inside
&lt;/h2&gt;

&lt;p&gt;Instead of just videos, I tried to make everything practical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js &amp;amp; Socket.io courses&lt;/strong&gt; — from scratch, with an English/Hinglish toggle (India-first audience)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A 24-topic roadmap&lt;/strong&gt; with progress tracking, so you always know what's next&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI mock interviews&lt;/strong&gt; — two interviewer personas that actually grill you and score you&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DSA practice&lt;/strong&gt; with a "select any line → AI explains it" helper&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live classes&lt;/strong&gt; with recordings + AI-generated notes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In-browser dev stack&lt;/strong&gt; — run MongoDB and code without any local setup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A "Backend Ready" certificate&lt;/strong&gt; you can only earn by proving skills (no participation trophies)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resume + portfolio builder&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Installable as a &lt;strong&gt;PWA&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The tech (for the curious)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; React + Vite → Netlify&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Node.js + Express (ESM), MongoDB + Mongoose → Render&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Realtime:&lt;/strong&gt; Socket.io for live classes/chat, WebRTC (mesh) for video rooms &amp;amp; 1:1 calls&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PWA:&lt;/strong&gt; service worker for install + web push notifications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI:&lt;/strong&gt; Anthropic / Gemini / Groq for the interview, explainers and notes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A few things I learned (the hard way)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WebRTC across mobile networks is brutal.&lt;/strong&gt; STUN alone isn't enough — symmetric NATs (hello, mobile data) need a TURN server. I spent way too long debugging "why won't the remote video show up."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache invalidation is genuinely one of the hard problems.&lt;/strong&gt; A stale server cache + client cache had me chasing "why isn't my new logo showing" far longer than I'd like to admit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shipping beats perfect.&lt;/strong&gt; It's not finished — but it's real, and it's out there.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  It's live — feedback welcome 🙏
&lt;/h2&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://asbackendinstitute.com" rel="noopener noreferrer"&gt;https://asbackendinstitute.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're learning backend (or teaching it), I'd love to hear what you'd want added. I'm actively building on it.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>beginners</category>
      <category>showdev</category>
    </item>
    <item>
      <title>dotenv-audit v1.1.0 — now with .env.example auto-sync</title>
      <dc:creator>Akash Gupta</dc:creator>
      <pubDate>Tue, 07 Apr 2026 19:09:09 +0000</pubDate>
      <link>https://dev.to/akashguptasky/dotenv-audit-v110-now-with-envexample-auto-sync-18ei</link>
      <guid>https://dev.to/akashguptasky/dotenv-audit-v110-now-with-envexample-auto-sync-18ei</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a follow-up to my previous article: &lt;a href="https://dev.to/akashguptasky/i-built-a-cli-tool-that-auto-detects-missing-environment-variables-no-schema-needed-gpn"&gt;I built a CLI tool that auto-detects missing environment variables — no schema needed&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Quick update on dotenv-audit — the CLI tool that scans your code and finds missing environment variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's new in v1.1.0
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;sync&lt;/code&gt; command — keep .env.example in sync with your code
&lt;/h3&gt;

&lt;p&gt;The most common problem with &lt;code&gt;.env.example&lt;/code&gt; files? They go outdated. Someone adds a new &lt;code&gt;process.env.STRIPE_KEY&lt;/code&gt; in code but forgets to update &lt;code&gt;.env.example&lt;/code&gt;. New developers clone the repo, miss the variable, and waste time debugging.&lt;/p&gt;

&lt;p&gt;Now just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx dotenv-audit &lt;span class="nb"&gt;sync&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;It will:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Scan your code for every process.env usage&lt;br&gt;
Compare with your existing .env.example&lt;br&gt;
Add missing variables with smart placeholder values&lt;br&gt;
Warn about unused variables that should be removed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .env.example&lt;/span&gt;
&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000
&lt;span class="nv"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;OLD_UNUSED_VAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;something
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After running npx dotenv-audit sync:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  dotenv-audit &lt;span class="nb"&gt;sync
  &lt;/span&gt;Scanned 12 files

  + 2 variable&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; missing from .env.example:
    + API_KEY        app.js:3
    + STRIPE_KEY     payments.ts:22

  - 1 variable&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; .env.example but not used &lt;span class="k"&gt;in &lt;/span&gt;code:
    - OLD_UNUSED_VAR

  ✓ Added 2 variable&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; to .env.example
  &lt;span class="o"&gt;!&lt;/span&gt; 1 unused variable&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; found — review and remove manually
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Your .env.example now has:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000
&lt;span class="nv"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;OLD_UNUSED_VAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;something

&lt;span class="c"&gt;# ── Added by dotenv-audit sync ──────────────&lt;/span&gt;
&lt;span class="c"&gt;# Other&lt;/span&gt;
&lt;span class="nv"&gt;API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_api_key_here

&lt;span class="c"&gt;# Stripe&lt;/span&gt;
&lt;span class="nv"&gt;STRIPE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk_test_your_stripe_secret_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Local .env file reading (bug fix in v1.0.3)
Previously the tool only checked process.env at runtime — so if you had variables in your .env file, they were still showing as "missing". Fixed. Now it reads .env and .env.local before validating.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;All commands&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx dotenv-audit              &lt;span class="c"&gt;# Scan and show missing vars&lt;/span&gt;
npx dotenv-audit &lt;span class="nt"&gt;--ask&lt;/span&gt;        &lt;span class="c"&gt;# Interactive mode (generate .env + ENV_SETUP.md)&lt;/span&gt;
npx dotenv-audit &lt;span class="nb"&gt;sync&lt;/span&gt;         &lt;span class="c"&gt;# Sync .env.example with code&lt;/span&gt;
npx dotenv-audit audit        &lt;span class="c"&gt;# List all detected variables&lt;/span&gt;
npx dotenv-audit gen          &lt;span class="c"&gt;# Generate .env.example from scratch&lt;/span&gt;
npx dotenv-audit &lt;span class="nt"&gt;--json&lt;/span&gt; &lt;span class="nt"&gt;--ci&lt;/span&gt;  &lt;span class="c"&gt;# CI mode with JSON output&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Try it&lt;/strong&gt;&lt;br&gt;
npx dotenv-audit sync&lt;br&gt;
npm: &lt;a href="https://www.npmjs.com/package/dotenv-audit" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/dotenv-audit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;400+ downloads in the first 2 days. Would love your feedback — what would you want next?&lt;/p&gt;




&lt;p&gt;Thanks for reading! If you missed the first article, check it out here: &lt;a href="https://dev.to/akashguptasky/i-built-a-cli-tool-that-auto-detects-missing-environment-variables-no-schema-needed-gpn"&gt;How I built dotenv-audit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find it useful, drop a ❤️ and share it with your team!&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>development</category>
    </item>
    <item>
      <title>I built a CLI tool that auto-detects missing environment variables — no schema needed</title>
      <dc:creator>Akash Gupta</dc:creator>
      <pubDate>Sun, 05 Apr 2026 19:35:26 +0000</pubDate>
      <link>https://dev.to/akashguptasky/i-built-a-cli-tool-that-auto-detects-missing-environment-variables-no-schema-needed-gpn</link>
      <guid>https://dev.to/akashguptasky/i-built-a-cli-tool-that-auto-detects-missing-environment-variables-no-schema-needed-gpn</guid>
      <description>&lt;p&gt;Every Node.js developer has faced this at least once:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;App crashes in production.&lt;br&gt;
"Cannot read property of undefined."&lt;br&gt;
2 hours of debugging later — someone forgot to set DATABASE_URL.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I got tired of this. So I built &lt;strong&gt;dotenv-audit&lt;/strong&gt; — a CLI tool that scans your actual code, finds every &lt;code&gt;process.env&lt;/code&gt; usage, and tells you exactly what's missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Existing Tools
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;dotenv&lt;/strong&gt; → loads &lt;code&gt;.env&lt;/code&gt; file. Doesn't validate anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;envalid&lt;/strong&gt; → validates, but you have to write a schema manually:&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;// With envalid - you write this for EVERY variable&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cleanEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;port&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;REDIS_HOST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="c1"&gt;// ... 20 more lines&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem? You already wrote &lt;code&gt;process .env.DATABASE_URL&lt;/code&gt; in your code. Why write it again in a schema?&lt;/p&gt;

&lt;p&gt;The Solution&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;npx&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;audit&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;ask&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. One command. It:&lt;/p&gt;

&lt;p&gt;Scans your .js, .ts, .jsx, .tsx, .vue, .svelte files&lt;br&gt;
Finds every &lt;code&gt;process.env.XXXX&lt;/code&gt; automatically&lt;br&gt;
Shows what's missing with exact file locations&lt;br&gt;
Generates a &lt;code&gt;.env&lt;/code&gt; file with smart placeholder values&lt;br&gt;
Output&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;dotenv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;audit&lt;/span&gt;  &lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;
  &lt;span class="err"&gt;──────────────────────────────────────────&lt;/span&gt;
  &lt;span class="nx"&gt;Scanned&lt;/span&gt; &lt;span class="mi"&gt;47&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="err"&gt;·&lt;/span&gt; &lt;span class="nx"&gt;Found&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="nx"&gt;variables&lt;/span&gt;

  &lt;span class="err"&gt;✗&lt;/span&gt; &lt;span class="nc"&gt;MISSING &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="err"&gt;✗&lt;/span&gt; &lt;span class="nx"&gt;DATABASE_URL&lt;/span&gt;
      &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;

    &lt;span class="err"&gt;✗&lt;/span&gt; &lt;span class="nx"&gt;JWT_SECRET&lt;/span&gt;
      &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;

    &lt;span class="err"&gt;✗&lt;/span&gt; &lt;span class="nx"&gt;STRIPE_KEY&lt;/span&gt;
      &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;payments&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;

  &lt;span class="err"&gt;⚠&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;verbose&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;see&lt;/span&gt; &lt;span class="nx"&gt;details&lt;/span&gt;

  &lt;span class="err"&gt;✓&lt;/span&gt; &lt;span class="nc"&gt;SET &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="err"&gt;──────────────────────────────────────────&lt;/span&gt;
  &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="nx"&gt;missing&lt;/span&gt; &lt;span class="err"&gt;·&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Smart &lt;code&gt;.env&lt;/code&gt; Generation&lt;br&gt;
When you run --ask mode, it asks:&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="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Generate&lt;/span&gt; &lt;span class="nx"&gt;ENV_SETUP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;missing&lt;/span&gt; &lt;span class="nx"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;yes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;no&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;yes&lt;/span&gt;
&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Create&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;missing&lt;/span&gt; &lt;span class="nx"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;yes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;no&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;yes&lt;/span&gt;
&lt;span class="nx"&gt;And&lt;/span&gt; &lt;span class="nx"&gt;generates&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;aware&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;


&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="err"&gt;──&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt; &lt;span class="err"&gt;────────────────────────────────&lt;/span&gt;
&lt;span class="nx"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;mongodb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:27017/your_database_name&lt;/span&gt;
&lt;span class="nx"&gt;REDIS_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;localhost&lt;/span&gt;
&lt;span class="nx"&gt;REDIS_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="err"&gt;──&lt;/span&gt; &lt;span class="nx"&gt;Authentication&lt;/span&gt; &lt;span class="err"&gt;──────────────────────────&lt;/span&gt;
&lt;span class="nx"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;your_jwt_secret_key_min_32_chars_long&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="err"&gt;──&lt;/span&gt; &lt;span class="nx"&gt;Stripe&lt;/span&gt; &lt;span class="err"&gt;──────────────────────────────────&lt;/span&gt;
&lt;span class="nx"&gt;STRIPE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;sk_test_your_stripe_secret_key_here&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="err"&gt;──&lt;/span&gt; &lt;span class="nx"&gt;AI&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;LLM&lt;/span&gt; &lt;span class="err"&gt;────────────────────────────────&lt;/span&gt;
&lt;span class="nx"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;sk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;your_openai_api_key_here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It even reads your &lt;code&gt;package.json&lt;/code&gt; — if you use &lt;code&gt;mongoose&lt;/code&gt;, it gives &lt;code&gt;mongodb://&lt;/code&gt; URLs. If you use &lt;code&gt;pg&lt;/code&gt;, it gives &lt;code&gt;postgresql://&lt;/code&gt; URLs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detection Patterns&lt;/strong&gt;&lt;br&gt;
It catches all the ways developers access env variables:&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;// All detected:&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATABASE_URL&lt;/span&gt;              &lt;span class="c1"&gt;// dot access&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;API_KEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;                &lt;span class="c1"&gt;// bracket access&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HOST&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;    &lt;span class="c1"&gt;// destructuring&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;              &lt;span class="c1"&gt;// defaults (shown as warning)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_API_URL&lt;/span&gt;         &lt;span class="c1"&gt;// Vite&lt;/span&gt;

&lt;span class="c1"&gt;// Smart filtering:&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEV&lt;/span&gt;                   &lt;span class="c1"&gt;// SKIPPED (Vite built-in)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MODE&lt;/span&gt;                  &lt;span class="c1"&gt;// SKIPPED (Vite built-in)&lt;/span&gt;
&lt;span class="c1"&gt;// process.env.COMMENTED              // SKIPPED (in comments)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Monorepo Support&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you have a monorepo (pnpm workspaces, lerna, turbo), it auto-detects services and creates separate .env files:&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="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Create&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="nx"&gt;inside&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="nx"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;yes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;no&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;yes&lt;/span&gt;

  &lt;span class="err"&gt;✓&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;          &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt; &lt;span class="nx"&gt;variables&lt;/span&gt;
  &lt;span class="err"&gt;✓&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;       &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="nx"&gt;variables&lt;/span&gt;
  &lt;span class="err"&gt;✓&lt;/span&gt; &lt;span class="nx"&gt;services&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="nx"&gt;variables&lt;/span&gt;

  &lt;span class="err"&gt;✓&lt;/span&gt; &lt;span class="nx"&gt;Done&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="nx"&gt;processed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more dumping all variables into one file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use in CI/CD&lt;/strong&gt;&lt;br&gt;
Add this to your GitHub Actions:&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="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Validate&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="nx"&gt;vars&lt;/span&gt;
  &lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;npx&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;audit&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;ci&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any required variable is missing, the pipeline fails — before your app does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Comparison&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;dotenv&lt;/th&gt;
&lt;th&gt;envalid&lt;/th&gt;
&lt;th&gt;dotenv-audit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Auto-detect from code&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zero schema needed&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generate &lt;code&gt;.env&lt;/code&gt; file&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database auto-detect&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monorepo support&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zero dependencies&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Try It&lt;/strong&gt;&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;npx&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;audit&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;ask&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;npm:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/dotenv-audit" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/dotenv-audit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is my first npm package. I'd genuinely love feedback — what features would make this more useful for your workflow?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href="https://dev.to/akashguptasky/dotenv-audit-v110-now-with-envexample-auto-sync-18ei"&gt;v1.1.0 released with .env.example auto-sync →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
