<?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>Forem: Nilesh Raut</title>
    <description>The latest articles on Forem by Nilesh Raut (@speaklouder).</description>
    <link>https://forem.com/speaklouder</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1027180%2Fe14fdd97-a2b6-47fe-a5a1-12628b3beca2.png</url>
      <title>Forem: Nilesh Raut</title>
      <link>https://forem.com/speaklouder</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/speaklouder"/>
    <language>en</language>
    <item>
      <title>From PR to Production: How Kubernetes Deployments Actually Work (Microservices in the Real World)</title>
      <dc:creator>Nilesh Raut</dc:creator>
      <pubDate>Sun, 22 Feb 2026 16:23:51 +0000</pubDate>
      <link>https://forem.com/speaklouder/from-pr-to-production-how-kubernetes-deployments-actually-work-microservices-in-the-real-world-1cfb</link>
      <guid>https://forem.com/speaklouder/from-pr-to-production-how-kubernetes-deployments-actually-work-microservices-in-the-real-world-1cfb</guid>
      <description>&lt;p&gt;Most developers know how to write code.&lt;/p&gt;

&lt;p&gt;Fewer understand what actually happens after clicking &lt;strong&gt;“&lt;a href="https://nileshblog.tech/from-code-to-kubernetes-production-deployment-guide/" rel="noopener noreferrer"&gt;Merge Pull Request&lt;/a&gt;.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And almost nobody truly understands what Kubernetes is doing during a &lt;a href="https://nileshblog.tech/from-code-to-kubernetes-production-deployment-guide/" rel="noopener noreferrer"&gt;production deployment&lt;/a&gt; — until something breaks.&lt;/p&gt;

&lt;p&gt;This post is a practical walkthrough of how code moves from PR → CI/CD → Helm → Kubernetes → Production, especially in a microservices setup.&lt;/p&gt;

&lt;p&gt;If you’ve ever shipped something that worked locally but behaved differently in production, this is for you.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohwndngd7zq2uujaumk6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohwndngd7zq2uujaumk6.png" alt="Pr to Prod" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  First: Kubernetes Doesn’t “Deploy” Your Code
&lt;/h2&gt;

&lt;p&gt;This mental model changes everything.&lt;/p&gt;

&lt;p&gt;Kubernetes doesn’t deploy applications the way we think about deployments.&lt;/p&gt;

&lt;p&gt;It maintains &lt;strong&gt;desired state&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You declare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“I want 3 replicas.”&lt;/li&gt;
&lt;li&gt;“I want image &lt;code&gt;order-service:1.4.2&lt;/code&gt;.”&lt;/li&gt;
&lt;li&gt;“I want these resource limits.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kubernetes continuously checks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does current state match desired state?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If not, it fixes it.&lt;/p&gt;

&lt;p&gt;That’s the entire system.&lt;/p&gt;

&lt;p&gt;Everything else — rolling updates, restarts, scaling — is just reconciliation.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens After You Merge a PR
&lt;/h2&gt;

&lt;p&gt;Let’s break this down in a real production workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — PR is merged
&lt;/h3&gt;

&lt;p&gt;You merge code into &lt;code&gt;main&lt;/code&gt; or &lt;code&gt;develop&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;No one logs into the cluster.&lt;/p&gt;

&lt;p&gt;No one runs &lt;code&gt;kubectl&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — CI/CD pipeline runs
&lt;/h3&gt;

&lt;p&gt;The pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runs tests (fail fast)&lt;/li&gt;
&lt;li&gt;Builds a Docker image&lt;/li&gt;
&lt;li&gt;Tags it (usually with commit SHA)&lt;/li&gt;
&lt;li&gt;Pushes it to a container registry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example image tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;order-service:1.4.2-a8f3d21
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One-line rule: Never use &lt;code&gt;latest&lt;/code&gt; in production.&lt;/p&gt;

&lt;p&gt;You want immutable, traceable builds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Deployment is triggered
&lt;/h3&gt;

&lt;p&gt;Two common approaches:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option A – CI runs Helm directly&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;helm upgrade order-service &lt;span class="nt"&gt;--set&lt;/span&gt; image.tag&lt;span class="o"&gt;=&lt;/span&gt;1.4.2-a8f3d21
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This updates the Kubernetes Deployment spec.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option B – GitOps (ArgoCD / Flux)&lt;/strong&gt;&lt;br&gt;
CI updates a config repo → GitOps controller detects change → syncs cluster.&lt;/p&gt;

&lt;p&gt;Either way, Kubernetes receives an updated Deployment object.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Kubernetes Actually Does Next
&lt;/h2&gt;

&lt;p&gt;This is where things get interesting.&lt;/p&gt;

&lt;p&gt;If the image tag changed inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;.spec.template&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kubernetes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates a new ReplicaSet&lt;/li&gt;
&lt;li&gt;Starts new pods with the new image&lt;/li&gt;
&lt;li&gt;Waits for readiness probe to succeed&lt;/li&gt;
&lt;li&gt;Gradually terminates old pods&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a rolling update.&lt;/p&gt;

&lt;p&gt;No downtime if configured correctly.&lt;/p&gt;

&lt;p&gt;No Helm magic.&lt;/p&gt;

&lt;p&gt;Just the Deployment controller doing its job.&lt;/p&gt;




&lt;h2&gt;
  
  
  Important: What Actually Triggers a Rollout
&lt;/h2&gt;

&lt;p&gt;Only changes inside &lt;code&gt;.spec.template&lt;/code&gt; trigger new ReplicaSets.&lt;/p&gt;

&lt;p&gt;Examples that trigger rollout:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Image change&lt;/li&gt;
&lt;li&gt;Environment variable change&lt;/li&gt;
&lt;li&gt;Resource limit change&lt;/li&gt;
&lt;li&gt;Container command change&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples that do NOT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changing replica count (only scales)&lt;/li&gt;
&lt;li&gt;Updating a Service&lt;/li&gt;
&lt;li&gt;Editing comments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding this prevents confusion in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  Small System vs Microservices: What Changes?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Small System (Single Service)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;One Deployment&lt;/li&gt;
&lt;li&gt;One Service&lt;/li&gt;
&lt;li&gt;One Helm chart&lt;/li&gt;
&lt;li&gt;One pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simple mental model.&lt;br&gt;
Easier debugging.&lt;br&gt;
Larger blast radius.&lt;/p&gt;

&lt;h3&gt;
  
  
  Microservices (Real World)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;auth-service&lt;/li&gt;
&lt;li&gt;order-service&lt;/li&gt;
&lt;li&gt;payment-service&lt;/li&gt;
&lt;li&gt;gateway&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Has its own Deployment&lt;/li&gt;
&lt;li&gt;Has its own Helm release&lt;/li&gt;
&lt;li&gt;Scales independently&lt;/li&gt;
&lt;li&gt;Deploys independently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When &lt;code&gt;order-service&lt;/code&gt; updates, only that Deployment rolls.&lt;/p&gt;

&lt;p&gt;Other services remain untouched.&lt;/p&gt;

&lt;p&gt;This isolation is the real advantage of microservices.&lt;/p&gt;

&lt;p&gt;But it comes with operational complexity.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real Production Mistakes I’ve Seen
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Memory limit reduced “just a little”
&lt;/h3&gt;

&lt;p&gt;Pods started OOM-killing under load during rollout.&lt;br&gt;
Traffic dropped.&lt;br&gt;
Rollback saved the night.&lt;/p&gt;

&lt;p&gt;Lesson: Resource changes are real deployments.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. ConfigMap updated but pods didn’t restart
&lt;/h3&gt;

&lt;p&gt;ConfigMap changes do not restart pods automatically.&lt;br&gt;
You must trigger rollout manually or use checksum annotations.&lt;/p&gt;

&lt;p&gt;Lesson: Not everything behaves how you expect.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Using &lt;code&gt;latest&lt;/code&gt; tag
&lt;/h3&gt;

&lt;p&gt;Rollback becomes unpredictable.&lt;br&gt;
You lose traceability.&lt;/p&gt;

&lt;p&gt;Lesson: Immutable image tags are non-negotiable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security Awareness in Deployment
&lt;/h2&gt;

&lt;p&gt;Things that matter more than people admit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No cluster-admin access for developers&lt;/li&gt;
&lt;li&gt;Proper RBAC&lt;/li&gt;
&lt;li&gt;Secrets stored securely (not in plain values.yaml)&lt;/li&gt;
&lt;li&gt;Resource limits on every container&lt;/li&gt;
&lt;li&gt;Liveness and readiness probes configured&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A deployment is also a security event.&lt;/p&gt;

&lt;p&gt;Treat it that way.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Engineering Mindset
&lt;/h2&gt;

&lt;p&gt;Don’t think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How do I deploy?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“What changed in &lt;code&gt;.spec.template&lt;/code&gt;?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you understand that, you understand Kubernetes deployments.&lt;/p&gt;

&lt;p&gt;Helm just renders YAML.&lt;/p&gt;

&lt;p&gt;CI just builds images.&lt;/p&gt;

&lt;p&gt;Kubernetes enforces desired state.&lt;/p&gt;

&lt;p&gt;That’s the real system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;Kubernetes deployments feel complex until you understand the reconciliation loop.&lt;/p&gt;

&lt;p&gt;Once you do, they become predictable.&lt;/p&gt;

&lt;p&gt;And predictability is what keeps production stable.&lt;/p&gt;

&lt;p&gt;If you want a deeper breakdown with diagrams, failure scenarios, and production war stories, I’ve written the full long-form version here:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://nileshblog.tech/from-code-to-kubernetes-production-deployment-guide/" rel="noopener noreferrer"&gt;https://nileshblog.tech/from-code-to-kubernetes-production-deployment-guide/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>productivity</category>
      <category>software</category>
      <category>git</category>
    </item>
    <item>
      <title>Why Your Node.js App Is Fast Locally but Slow in Production</title>
      <dc:creator>Nilesh Raut</dc:creator>
      <pubDate>Wed, 18 Feb 2026 21:18:00 +0000</pubDate>
      <link>https://forem.com/speaklouder/why-your-nodejs-app-is-fast-locally-but-slow-in-production-2j1k</link>
      <guid>https://forem.com/speaklouder/why-your-nodejs-app-is-fast-locally-but-slow-in-production-2j1k</guid>
      <description>&lt;p&gt;If you’ve built a Node.js app, you’ve probably experienced this exact moment:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“It’s blazing fast on my laptop… why is it crawling in production?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This isn’t bad luck. It’s a pattern. I’ve seen it across startups, scale-ups, and even mature systems. The gap between &lt;strong&gt;&lt;a href="https://nileshblog.tech/nodejs-run-fast-locally-slow-in-production/" rel="noopener noreferrer"&gt;local performance&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://nileshblog.tech/nodejs-run-fast-locally-slow-in-production/" rel="noopener noreferrer"&gt;production performance&lt;/a&gt;&lt;/strong&gt; exists because production is a completely different environment — more users, more network hops, more failure modes, and far fewer shortcuts.&lt;/p&gt;

&lt;p&gt;Let’s break down the real reasons this happens and what actually fixes it.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Your Local Machine Is Lying to You
&lt;/h2&gt;

&lt;p&gt;Locally, everything is optimized in your favor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requests come from &lt;code&gt;localhost&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Database runs on the same machine&lt;/li&gt;
&lt;li&gt;No real network latency&lt;/li&gt;
&lt;li&gt;Almost zero concurrency&lt;/li&gt;
&lt;li&gt;Warm caches&lt;/li&gt;
&lt;li&gt;No security layers slowing things down&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Production doesn’t have that luxury.&lt;/p&gt;

&lt;p&gt;In production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every request crosses networks&lt;/li&gt;
&lt;li&gt;Databases are remote&lt;/li&gt;
&lt;li&gt;TLS is enabled&lt;/li&gt;
&lt;li&gt;Load balancers exist&lt;/li&gt;
&lt;li&gt;Multiple users hit the same resources at once&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your app isn’t slower. &lt;strong&gt;Reality is heavier.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Database Latency Is the Silent Killer
&lt;/h2&gt;

&lt;p&gt;Locally, a database query might take 2–5 ms.&lt;br&gt;
In production, that same query can take 50–200 ms.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network round trips&lt;/li&gt;
&lt;li&gt;Cold caches&lt;/li&gt;
&lt;li&gt;Larger datasets&lt;/li&gt;
&lt;li&gt;Missing indexes&lt;/li&gt;
&lt;li&gt;Shared database load&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A classic example:&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;await&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;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This feels instant locally with 100 rows.&lt;br&gt;
In production with millions of records and no index? It’s a time bomb.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add proper indexes&lt;/li&gt;
&lt;li&gt;Log slow queries&lt;/li&gt;
&lt;li&gt;Never assume “simple queries” are cheap&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  3. Connection Pooling Misconfigurations
&lt;/h2&gt;

&lt;p&gt;One of the most common Node.js production issues.&lt;/p&gt;

&lt;p&gt;Locally, you might run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 Node process&lt;/li&gt;
&lt;li&gt;1 database connection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple Node processes&lt;/li&gt;
&lt;li&gt;Each opens its own DB connections&lt;/li&gt;
&lt;li&gt;Database connection limit gets exhausted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Symptoms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Random slowness&lt;/li&gt;
&lt;li&gt;Timeouts&lt;/li&gt;
&lt;li&gt;Requests hanging without errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure connection pools explicitly&lt;/li&gt;
&lt;li&gt;Align pool size with DB limits&lt;/li&gt;
&lt;li&gt;Monitor active connections&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don’t control this, your app collapses under load.&lt;/p&gt;


&lt;h2&gt;
  
  
  4. Blocking the Event Loop (Without Realizing It)
&lt;/h2&gt;

&lt;p&gt;Node.js is fast — until you block it.&lt;/p&gt;

&lt;p&gt;Common production-only blockers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Heavy JSON parsing&lt;/li&gt;
&lt;li&gt;Synchronous file operations&lt;/li&gt;
&lt;li&gt;CPU-heavy loops&lt;/li&gt;
&lt;li&gt;Poorly written logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This code looks harmless:&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;largePayload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under real traffic, it can freeze your server.&lt;/p&gt;

&lt;p&gt;Locally, you never notice it.&lt;br&gt;
In production, concurrency exposes it instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid sync operations&lt;/li&gt;
&lt;li&gt;Offload CPU work to workers&lt;/li&gt;
&lt;li&gt;Measure event loop lag&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  5. Missing Timeouts Everywhere
&lt;/h2&gt;

&lt;p&gt;Local environments forgive mistakes. Production doesn’t.&lt;/p&gt;

&lt;p&gt;Without timeouts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;External APIs hang&lt;/li&gt;
&lt;li&gt;Database calls stall&lt;/li&gt;
&lt;li&gt;Requests pile up&lt;/li&gt;
&lt;li&gt;Node keeps waiting forever&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eventually, everything slows down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;br&gt;
Always define timeouts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP clients&lt;/li&gt;
&lt;li&gt;Database queries&lt;/li&gt;
&lt;li&gt;Internal service calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Timeouts are not pessimism — they are survival.&lt;/p&gt;


&lt;h2&gt;
  
  
  6. Logging Becomes a Performance Problem
&lt;/h2&gt;

&lt;p&gt;In development, logging is cheap.&lt;br&gt;
In production, logging can destroy performance.&lt;/p&gt;

&lt;p&gt;Reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Synchronous log writes&lt;/li&gt;
&lt;li&gt;Console logging under high load&lt;/li&gt;
&lt;li&gt;Log aggregation delays&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This line can be surprisingly expensive:&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multiply it by thousands of requests per second.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use async loggers&lt;/li&gt;
&lt;li&gt;Reduce log volume&lt;/li&gt;
&lt;li&gt;Never log large payloads by default&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. Scaling Without Understanding Throughput
&lt;/h2&gt;

&lt;p&gt;Adding more servers doesn’t always help.&lt;/p&gt;

&lt;p&gt;If your bottleneck is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single database&lt;/li&gt;
&lt;li&gt;A shared cache&lt;/li&gt;
&lt;li&gt;A rate-limited API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Horizontal scaling just amplifies the problem.&lt;/p&gt;

&lt;p&gt;This is why apps feel &lt;em&gt;slower&lt;/em&gt; after scaling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identify the real bottleneck&lt;/li&gt;
&lt;li&gt;Scale databases and caches intentionally&lt;/li&gt;
&lt;li&gt;Add backpressure and rate limits&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. You’re Not Testing Production-Like Load
&lt;/h2&gt;

&lt;p&gt;Most teams test functionality, not behavior under stress.&lt;/p&gt;

&lt;p&gt;Local testing usually means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One request at a time&lt;/li&gt;
&lt;li&gt;Clean startup state&lt;/li&gt;
&lt;li&gt;Happy paths only&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Production means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traffic spikes&lt;/li&gt;
&lt;li&gt;Slow dependencies&lt;/li&gt;
&lt;li&gt;Partial failures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load test before release&lt;/li&gt;
&lt;li&gt;Test with realistic data sizes&lt;/li&gt;
&lt;li&gt;Simulate failures, not just success&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;&lt;a href="https://nileshblog.tech/nodejs-run-fast-locally-slow-in-production/" rel="noopener noreferrer"&gt;Your Node.js app isn’t “slow in production.”&lt;/a&gt;&lt;br&gt;
It’s &lt;strong&gt;honest in production&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Local environments hide latency, concurrency, and failure. Production exposes them all at once.&lt;/p&gt;

&lt;p&gt;If you want consistent performance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Respect the network&lt;/li&gt;
&lt;li&gt;Measure everything&lt;/li&gt;
&lt;li&gt;Design for concurrency&lt;/li&gt;
&lt;li&gt;Expect things to fail&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fast local performance is a confidence boost.&lt;br&gt;
Fast production performance is an engineering achievement.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>productivity</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Idempotency: The Concept Everyone Mentions but Few Implement Correctly</title>
      <dc:creator>Nilesh Raut</dc:creator>
      <pubDate>Mon, 16 Feb 2026 20:06:00 +0000</pubDate>
      <link>https://forem.com/speaklouder/idempotency-the-concept-everyone-mentions-but-few-implement-correctly-2pbc</link>
      <guid>https://forem.com/speaklouder/idempotency-the-concept-everyone-mentions-but-few-implement-correctly-2pbc</guid>
      <description>&lt;p&gt;&lt;a href="https://nileshblog.tech/idempotency-explained-designing-retry-safe-apis/" rel="noopener noreferrer"&gt;Idempotency&lt;/a&gt; is one of those words that shows up everywhere: system design interviews, API docs, architecture diagrams, and postmortems. Everyone nods when it’s mentioned. Few teams actually implement it correctly.&lt;/p&gt;

&lt;p&gt;I’ve seen idempotency “implemented” with comments, flags, retries, or blind faith in the network. And I’ve also seen real production outages that could have been avoided with a proper idempotency strategy.&lt;/p&gt;

&lt;p&gt;This article is about what idempotency &lt;em&gt;really&lt;/em&gt; means in practice, where it breaks down, and how to implement it in real systems—not slides.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Idempotency Actually Means (Beyond the Definition)
&lt;/h2&gt;

&lt;p&gt;The textbook definition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An operation is idempotent if performing it multiple times has the same effect as performing it once.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s technically correct but operationally incomplete.&lt;/p&gt;

&lt;p&gt;In real systems, &lt;a href="https://nileshblog.tech/idempotency-explained-designing-retry-safe-apis/" rel="noopener noreferrer"&gt;idempotency&lt;/a&gt; is about &lt;strong&gt;protecting your system from duplicates caused by retries, timeouts, race conditions, and partial failures&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If your API client retries because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the network dropped,&lt;/li&gt;
&lt;li&gt;the load balancer timed out,&lt;/li&gt;
&lt;li&gt;the user double-clicked,&lt;/li&gt;
&lt;li&gt;a worker crashed mid-request,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;your system should not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;charge twice,&lt;/li&gt;
&lt;li&gt;create duplicate records,&lt;/li&gt;
&lt;li&gt;send duplicate emails,&lt;/li&gt;
&lt;li&gt;corrupt state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s the real problem idempotency solves.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Idempotency Matters (and Where It Doesn’t)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Common places it &lt;strong&gt;does&lt;/strong&gt; matter
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Payments and billing&lt;/li&gt;
&lt;li&gt;Order creation&lt;/li&gt;
&lt;li&gt;Inventory reservations&lt;/li&gt;
&lt;li&gt;Webhooks&lt;/li&gt;
&lt;li&gt;Background jobs and queues&lt;/li&gt;
&lt;li&gt;External API integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Places it usually &lt;strong&gt;doesn’t&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Pure reads (&lt;code&gt;GET&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Analytics counters (if approximate is acceptable)&lt;/li&gt;
&lt;li&gt;Fire-and-forget logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If an operation changes money, state, or inventory, idempotency is not optional.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Biggest Misconception: “POST Is Not Idempotent”
&lt;/h2&gt;

&lt;p&gt;You’ll often hear:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;GET is idempotent, POST is not.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s an HTTP convention, not a system guarantee.&lt;/p&gt;

&lt;p&gt;You can (and often must) make POST requests idempotent at the application level. Payments APIs do this all the time.&lt;/p&gt;

&lt;p&gt;The HTTP method does not save you. Your backend design does.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Naive (and Wrong) Implementations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. “We Just Retry”
&lt;/h3&gt;

&lt;p&gt;Retries without idempotency &lt;strong&gt;multiply bugs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If your payment service retries blindly and your backend creates a new record each time, you’ve just automated duplication.&lt;/p&gt;

&lt;p&gt;Retries are only safe &lt;em&gt;after&lt;/em&gt; idempotency is enforced.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. “We Check If It Exists”
&lt;/h3&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;
&lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="k"&gt;INSERT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This fails under concurrency.&lt;/p&gt;

&lt;p&gt;Two requests arrive at the same time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;both see “not exists”&lt;/li&gt;
&lt;li&gt;both insert&lt;/li&gt;
&lt;li&gt;congratulations, you have duplicates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a race condition, not idempotency.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. “We Use a Boolean Flag”
&lt;/h3&gt;

&lt;p&gt;Flags like &lt;code&gt;is_processed = true&lt;/code&gt; work only if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the operation is atomic&lt;/li&gt;
&lt;li&gt;the write is guaranteed to happen once&lt;/li&gt;
&lt;li&gt;there’s no partial failure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In distributed systems, those assumptions rarely hold.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Correct Mental Model
&lt;/h2&gt;

&lt;p&gt;Idempotency is about &lt;strong&gt;deduplicating intent&lt;/strong&gt;, not requests.&lt;/p&gt;

&lt;p&gt;You don’t care how many times a request arrives.&lt;br&gt;
You care that the &lt;em&gt;same logical action&lt;/em&gt; is processed once.&lt;/p&gt;

&lt;p&gt;That’s why idempotency keys exist.&lt;/p&gt;


&lt;h2&gt;
  
  
  Idempotency Keys: The Foundation
&lt;/h2&gt;

&lt;p&gt;An idempotency key is a &lt;strong&gt;client-generated unique identifier&lt;/strong&gt; for a logical operation.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Idempotency-Key: 7f3c9c2e-...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same logical action → same key&lt;/li&gt;
&lt;li&gt;Different action → different key&lt;/li&gt;
&lt;li&gt;Client must retry with the same key&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  A Minimal, Correct Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Store the key
&lt;/h3&gt;

&lt;p&gt;Create a table or cache entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;idempotency_key
request_hash
response
status
created_at
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Enforce uniqueness
&lt;/h3&gt;

&lt;p&gt;The key must be unique at the database or cache level.&lt;br&gt;
This prevents race conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: On request
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Check if the key exists&lt;/li&gt;
&lt;li&gt;If yes:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;return the stored response&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If no:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;process the request&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;store the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;return it&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retries are safe&lt;/li&gt;
&lt;li&gt;duplicates are impossible&lt;/li&gt;
&lt;li&gt;responses are consistent&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Handling Partial Failures (The Hard Part)
&lt;/h2&gt;

&lt;p&gt;What if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the operation succeeds,&lt;/li&gt;
&lt;li&gt;but the response fails to return?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without idempotency, the client retries and triggers a duplicate.&lt;/p&gt;

&lt;p&gt;With idempotency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the retry hits the same key&lt;/li&gt;
&lt;li&gt;you return the stored success response&lt;/li&gt;
&lt;li&gt;the system remains consistent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where most “implementations” fail—they don’t store the response.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Example: Payments
&lt;/h2&gt;

&lt;p&gt;Payment providers treat idempotency as mandatory.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Networks are unreliable&lt;/li&gt;
&lt;li&gt;Clients retry aggressively&lt;/li&gt;
&lt;li&gt;Money cannot be duplicated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A payment API without idempotency is reckless.&lt;/p&gt;

&lt;p&gt;The same logic applies to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;order creation&lt;/li&gt;
&lt;li&gt;inventory deduction&lt;/li&gt;
&lt;li&gt;subscription changes&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Performance and Storage Trade-offs
&lt;/h2&gt;

&lt;p&gt;Idempotency isn’t free.&lt;/p&gt;

&lt;p&gt;Costs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;extra storage&lt;/li&gt;
&lt;li&gt;lookup overhead&lt;/li&gt;
&lt;li&gt;TTL management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optimizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Redis with TTL for short-lived operations&lt;/li&gt;
&lt;li&gt;Use DB for long-lived financial records&lt;/li&gt;
&lt;li&gt;Expire keys safely (not too early)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Never trade correctness for &lt;a href="https://nileshblog.tech/idempotency-explained-designing-retry-safe-apis/" rel="noopener noreferrer"&gt;micro-optimizations&lt;/a&gt; here.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security Considerations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Treat idempotency keys as untrusted input&lt;/li&gt;
&lt;li&gt;Scope keys per user or client&lt;/li&gt;
&lt;li&gt;Avoid global collisions&lt;/li&gt;
&lt;li&gt;Don’t allow attackers to replay sensitive actions indefinitely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Idempotency improves safety, but careless design can introduce replay risks.&lt;/p&gt;




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

&lt;p&gt;Idempotency is not a buzzword. It’s a discipline.&lt;/p&gt;

&lt;p&gt;If your system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retries requests,&lt;/li&gt;
&lt;li&gt;talks over a network,&lt;/li&gt;
&lt;li&gt;processes money or state,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;then idempotency is part of your correctness model, not an “extra feature.”&lt;/p&gt;

&lt;p&gt;Most bugs blamed on “network issues” are actually idempotency failures.&lt;/p&gt;

&lt;p&gt;Implement it once. Implement it right. Your future self—and your on-call rotation—will thank you.&lt;/p&gt;

</description>
      <category>software</category>
      <category>systemdesign</category>
      <category>backend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Redis Is Not a Database (Until You Treat It Like One)</title>
      <dc:creator>Nilesh Raut</dc:creator>
      <pubDate>Fri, 13 Feb 2026 19:09:28 +0000</pubDate>
      <link>https://forem.com/speaklouder/redis-is-not-a-database-until-you-treat-it-like-one-11j8</link>
      <guid>https://forem.com/speaklouder/redis-is-not-a-database-until-you-treat-it-like-one-11j8</guid>
      <description>&lt;p&gt;Redis is one of those tools almost every backend engineer has used—and many have misused.&lt;/p&gt;

&lt;p&gt;It starts simple: &lt;em&gt;“Let’s just cache it.”&lt;/em&gt;&lt;br&gt;
Then Redis works so well that it slowly becomes &lt;em&gt;the system&lt;/em&gt;.&lt;br&gt;
Before you know it, business logic depends on Redis keys, not your primary database.&lt;/p&gt;

&lt;p&gt;That’s where things usually go wrong.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nileshblog.tech/redis-is-not-a-database-until-you-treat-it-like-one/" rel="noopener noreferrer"&gt;Redis &lt;/a&gt;is &lt;strong&gt;not&lt;/strong&gt; a database by default.&lt;br&gt;
But with the right discipline, configuration, and mindset—it &lt;em&gt;can&lt;/em&gt; behave like one.&lt;/p&gt;

&lt;p&gt;This article is about drawing that line clearly, from real production experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why &lt;a href="https://nileshblog.tech/redis-is-not-a-database-until-you-treat-it-like-one/" rel="noopener noreferrer"&gt;Redis Is Not a Database&lt;/a&gt; (By Default)
&lt;/h2&gt;

&lt;p&gt;Redis was designed for &lt;strong&gt;speed first&lt;/strong&gt;, durability second.&lt;/p&gt;

&lt;p&gt;Out of the box, Redis optimizes for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In-memory access&lt;/li&gt;
&lt;li&gt;Low latency&lt;/li&gt;
&lt;li&gt;Simple data structures&lt;/li&gt;
&lt;li&gt;Fast eviction and expiration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What it does &lt;em&gt;not&lt;/em&gt; guarantee by default:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strong durability&lt;/li&gt;
&lt;li&gt;Crash-safe persistence&lt;/li&gt;
&lt;li&gt;Complex querying&lt;/li&gt;
&lt;li&gt;Schema enforcement&lt;/li&gt;
&lt;li&gt;Long-term data retention&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you treat Redis like PostgreSQL without adjusting anything, you’re setting yourself up for silent data loss.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Common Trap: “It’s Just Temporary”
&lt;/h2&gt;

&lt;p&gt;Most Redis usage begins as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Session storage&lt;/li&gt;
&lt;li&gt;Cache layer&lt;/li&gt;
&lt;li&gt;Rate limiting&lt;/li&gt;
&lt;li&gt;Feature flags&lt;/li&gt;
&lt;li&gt;Counters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All fine use cases.&lt;/p&gt;

&lt;p&gt;The problem appears when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redis becomes the &lt;strong&gt;only&lt;/strong&gt; source of truth&lt;/li&gt;
&lt;li&gt;Writes happen &lt;strong&gt;only&lt;/strong&gt; to Redis&lt;/li&gt;
&lt;li&gt;The database becomes “optional”&lt;/li&gt;
&lt;li&gt;TTLs are misunderstood or ignored&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At that point, Redis is no longer a cache.&lt;br&gt;
It’s an &lt;em&gt;undeclared database&lt;/em&gt;—and an unsafe one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Persistence: The First Reality Check
&lt;/h2&gt;

&lt;p&gt;Redis persistence is &lt;strong&gt;opt-in&lt;/strong&gt; and &lt;strong&gt;configurable&lt;/strong&gt;, not guaranteed.&lt;/p&gt;

&lt;h3&gt;
  
  
  RDB (Snapshots)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Periodic point-in-time dumps&lt;/li&gt;
&lt;li&gt;Fast restarts&lt;/li&gt;
&lt;li&gt;Risk of losing recent writes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One-line explanation: &lt;em&gt;Good for caches, dangerous for critical writes.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  AOF (Append-Only File)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Logs every write operation&lt;/li&gt;
&lt;li&gt;Better durability&lt;/li&gt;
&lt;li&gt;Slower writes and larger disk usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One-line explanation: &lt;em&gt;Closer to database behavior, but still not perfect.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  AOF + RDB
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Common production setup&lt;/li&gt;
&lt;li&gt;Balances performance and recovery time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One-line explanation: &lt;em&gt;Still requires testing, monitoring, and discipline.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you haven’t tested:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Power loss&lt;/li&gt;
&lt;li&gt;Container restarts&lt;/li&gt;
&lt;li&gt;Disk-full scenarios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t know how durable your Redis really is.&lt;/p&gt;




&lt;h2&gt;
  
  
  Redis Without Backups Is a Risk, Not a System
&lt;/h2&gt;

&lt;p&gt;In real systems, I’ve seen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entire user sessions wiped during deploys&lt;/li&gt;
&lt;li&gt;Order states lost after node crashes&lt;/li&gt;
&lt;li&gt;Feature flags reset during failover&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All because Redis persistence was assumed, not verified.&lt;/p&gt;

&lt;p&gt;If Redis contains anything you cannot afford to lose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable persistence explicitly&lt;/li&gt;
&lt;li&gt;Back it up externally&lt;/li&gt;
&lt;li&gt;Monitor persistence failures&lt;/li&gt;
&lt;li&gt;Test restores regularly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Databases are boring because they survive disasters.&lt;br&gt;
Redis is fast because it assumes you know what you’re doing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Concurrency: Redis Is Atomic, Not Magical
&lt;/h2&gt;

&lt;p&gt;Redis commands are atomic—but your system logic may not be.&lt;/p&gt;

&lt;p&gt;Problems appear when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple keys must change together&lt;/li&gt;
&lt;li&gt;Business rules span multiple operations&lt;/li&gt;
&lt;li&gt;Failures happen mid-flow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Solutions Redis gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transactions (&lt;code&gt;MULTI/EXEC&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Lua scripts&lt;/li&gt;
&lt;li&gt;Single-threaded execution model&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One-line explanation: &lt;em&gt;You must design atomicity explicitly, not assume it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you’re modeling workflows, reservations, or financial state—Lua scripting is not optional.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Redis &lt;em&gt;Can&lt;/em&gt; Act Like a Database
&lt;/h2&gt;

&lt;p&gt;Redis starts behaving like a database only when you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable and test persistence&lt;/li&gt;
&lt;li&gt;Design for crash recovery&lt;/li&gt;
&lt;li&gt;Use Lua for invariants&lt;/li&gt;
&lt;li&gt;Avoid TTLs for critical data&lt;/li&gt;
&lt;li&gt;Replicate and monitor aggressively&lt;/li&gt;
&lt;li&gt;Treat memory limits seriously&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, Redis stops being “just a cache” and becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A fast primary store&lt;/li&gt;
&lt;li&gt;A coordination layer&lt;/li&gt;
&lt;li&gt;A real-time state engine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But note the cost: &lt;strong&gt;engineering effort&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Small Systems vs Large Systems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Small Systems
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Redis as cache only&lt;/li&gt;
&lt;li&gt;Database as source of truth&lt;/li&gt;
&lt;li&gt;Occasional Redis loss is acceptable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the safest setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Large Systems
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Redis used for locks, counters, queues, reservations&lt;/li&gt;
&lt;li&gt;Database writes are async&lt;/li&gt;
&lt;li&gt;Redis outages cause business impact&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here, Redis must be engineered like a database—or removed from the critical path.&lt;/p&gt;

&lt;p&gt;There is no middle ground.&lt;/p&gt;




&lt;p&gt;Common issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unauthenticated Redis exposed internally&lt;/li&gt;
&lt;li&gt;Accidental &lt;code&gt;FLUSHALL&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Memory exhaustion causing eviction&lt;/li&gt;
&lt;li&gt;Replica lag causing stale reads&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Mental Model That Actually Works
&lt;/h2&gt;

&lt;p&gt;Use this rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If Redis data disappears, can my system recover automatically?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Yes&lt;/strong&gt; → Redis is a cache.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No&lt;/strong&gt; → Redis is a database, whether you admit it or not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once Redis becomes unrecoverable state, you must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Engineer it like a database&lt;/li&gt;
&lt;li&gt;Or redesign the system&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Redis is an incredible tool—but it’s honest about what it is.&lt;/p&gt;

&lt;p&gt;It will not stop you from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Losing data&lt;/li&gt;
&lt;li&gt;Overloading memory&lt;/li&gt;
&lt;li&gt;Designing unsafe flows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That responsibility is yours.&lt;/p&gt;

&lt;p&gt;Treat Redis lightly, and it will betray you quietly.&lt;br&gt;
Treat it like a database, and it will reward you with speed most systems can only dream of.&lt;/p&gt;

&lt;p&gt;The danger isn’t Redis.&lt;br&gt;
The danger is pretending it’s something it never promised to be.&lt;/p&gt;

</description>
      <category>redis</category>
      <category>software</category>
      <category>discuss</category>
      <category>database</category>
    </item>
    <item>
      <title>20+ Git Commands Every Software Engineer Should Actually Know</title>
      <dc:creator>Nilesh Raut</dc:creator>
      <pubDate>Sat, 31 Jan 2026 04:07:31 +0000</pubDate>
      <link>https://forem.com/speaklouder/20-git-commands-every-software-engineer-should-actually-know-1gnf</link>
      <guid>https://forem.com/speaklouder/20-git-commands-every-software-engineer-should-actually-know-1gnf</guid>
      <description>&lt;p&gt;Most engineers use Git every day—but only a handful of commands.&lt;br&gt;
That’s fine… until something goes wrong.&lt;/p&gt;

&lt;p&gt;A bad merge.&lt;br&gt;
A wrong commit.&lt;br&gt;
A force-push panic.&lt;/p&gt;

&lt;p&gt;This list covers &lt;strong&gt;&lt;a href="https://nileshblog.tech/20-git-commands-every-software-engineer-should-know/" rel="noopener noreferrer"&gt;20+ Git commands&lt;/a&gt;&lt;/strong&gt; you’ll actually use in real projects, with &lt;strong&gt;one-line explanations&lt;/strong&gt; so you know &lt;em&gt;what they do and when to use them&lt;/em&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Core &lt;a href="https://nileshblog.tech/20-git-commands-every-software-engineer-should-know/" rel="noopener noreferrer"&gt;Git Commands&lt;/a&gt; Basics
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. &lt;code&gt;git init&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Creates a new Git repository in the current directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. &lt;code&gt;git clone&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Downloads an existing remote repository to your local machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;repo-url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. &lt;code&gt;git status&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Shows the current state of files (modified, staged, untracked).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. &lt;code&gt;git add&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Stages files so they’re included in the next 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 &lt;span class="nb"&gt;.&lt;/span&gt;
git add file.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  5. &lt;code&gt;git commit&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Saves staged changes as a snapshot with a message.&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;-m&lt;/span&gt; &lt;span class="s2"&gt;"message"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  6. &lt;code&gt;git push&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Uploads local commits to the remote repository.&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 origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  7. &lt;code&gt;git pull&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Fetches remote changes and merges them into your branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git pull
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Branching &amp;amp; Navigation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  8. &lt;code&gt;git branch&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Lists branches or creates a new branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch
git branch feature-x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  9. &lt;code&gt;git checkout&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Switches branches or restores files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout feature-x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  10. &lt;code&gt;git switch&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A cleaner, modern way to switch branches.&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  11. &lt;code&gt;git merge&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Combines another branch into the current branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git merge feature-x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  12. &lt;code&gt;git log&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Shows commit history for the current branch.&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;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Undoing Mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  13. &lt;code&gt;git reset&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Moves HEAD and optionally discards commits or 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
git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; HEAD~1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  14. &lt;code&gt;git revert&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Creates a new commit that safely undoes an older 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 revert &amp;lt;commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  15. &lt;code&gt;git checkout -- &amp;lt;file&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Discards local changes to a specific file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;--&lt;/span&gt; index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Temporary Work
&lt;/h2&gt;

&lt;h3&gt;
  
  
  16. &lt;code&gt;git stash&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Temporarily saves uncommitted 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 stash
git stash pop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  17. &lt;code&gt;git stash list&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Shows all saved stashes.&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 list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Working With Remotes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  18. &lt;code&gt;git remote -v&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Displays configured remote repositories.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  19. &lt;code&gt;git fetch&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Downloads remote changes without merging them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Inspecting Changes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  20. &lt;code&gt;git diff&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Shows differences between files, commits, or stages.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  21. &lt;code&gt;git blame&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Shows who last modified each line of a file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git blame file.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  22. &lt;code&gt;git show&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Displays detailed information about a specific 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 show &amp;lt;commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Cleanup &amp;amp; Recovery
&lt;/h2&gt;

&lt;h3&gt;
  
  
  23. &lt;code&gt;git clean&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Removes untracked files from the working directory.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  24. &lt;code&gt;git reflog&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Shows every move of HEAD, even deleted or lost commits.&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How Senior Engineers Actually Use Git
&lt;/h2&gt;

&lt;p&gt;Senior engineers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;check &lt;code&gt;git status&lt;/code&gt; constantly,&lt;/li&gt;
&lt;li&gt;prefer &lt;code&gt;revert&lt;/code&gt; over &lt;code&gt;reset&lt;/code&gt; on shared branches,&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;fetch&lt;/code&gt; before risky merges,&lt;/li&gt;
&lt;li&gt;rely on &lt;code&gt;reflog&lt;/code&gt; when things go wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Git isn’t just version control—it’s your &lt;strong&gt;safety net&lt;/strong&gt;.&lt;/p&gt;




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

&lt;p&gt;You don’t need to memorize Git.&lt;br&gt;
You need to &lt;strong&gt;understand enough to recover when things break&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Master these commands and you’ll:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;move faster,&lt;/li&gt;
&lt;li&gt;panic less,&lt;/li&gt;
&lt;li&gt;and collaborate better.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Git won’t make you a better engineer—but &lt;strong&gt;not knowing Git can absolutely make you a worse one&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>git</category>
      <category>software</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Vibe Coding vs Engineering Judgment: Where Speed Ends and Responsibility Begins</title>
      <dc:creator>Nilesh Raut</dc:creator>
      <pubDate>Wed, 14 Jan 2026 14:42:57 +0000</pubDate>
      <link>https://forem.com/speaklouder/vibe-coding-vs-engineering-judgment-where-speed-ends-and-responsibility-begins-5fpn</link>
      <guid>https://forem.com/speaklouder/vibe-coding-vs-engineering-judgment-where-speed-ends-and-responsibility-begins-5fpn</guid>
      <description>&lt;p&gt;Right now, vibe coding is everywhere.&lt;/p&gt;

&lt;p&gt;You prompt an AI, stay in flow, generate code quickly, and ship something that &lt;em&gt;looks&lt;/em&gt; correct. Demos work. Tests pass. It feels productive.&lt;/p&gt;

&lt;p&gt;And then production reminds you why engineering exists.&lt;/p&gt;

&lt;p&gt;This post isn’t anti-AI. I use AI daily. But after working on real systems, handling incidents, and reviewing production code, one thing has become clear:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vibe coding accelerates output. &lt;a href="https://nileshblog.tech/vibe-coding-vs-engineering-judgment-why-speed-alone-cant-ship-reliable-software/" rel="noopener noreferrer"&gt;Engineering judgment&lt;/a&gt; protects systems.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You need both—but they solve very different problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  What People Actually Mean by Vibe Coding
&lt;/h2&gt;

&lt;p&gt;Vibe coding usually looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rapid AI-assisted code generation,&lt;/li&gt;
&lt;li&gt;minimal planning,&lt;/li&gt;
&lt;li&gt;trusting the output because “it works”,&lt;/li&gt;
&lt;li&gt;prioritizing momentum over structure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s popular because it removes friction. No blank page. No syntax struggles. No context switching.&lt;/p&gt;

&lt;p&gt;For the right use cases, that’s a real advantage.&lt;/p&gt;

&lt;p&gt;The problem starts when speed becomes the goal instead of correctness.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Vibe Coding Feels So Effective
&lt;/h2&gt;

&lt;p&gt;Vibe coding works because it eliminates pain points developers hate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;staring at an empty file,&lt;/li&gt;
&lt;li&gt;boilerplate work,&lt;/li&gt;
&lt;li&gt;repetitive setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI fills gaps instantly and keeps you moving. For small scopes, this is a genuine productivity boost.&lt;/p&gt;

&lt;p&gt;But momentum without judgment doesn’t equal progress—it just means you’re moving fast in &lt;em&gt;some&lt;/em&gt; direction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Vibe Coding Works Well ✅
&lt;/h2&gt;

&lt;p&gt;Let’s be honest about where vibe coding shines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disposable Prototypes
&lt;/h3&gt;

&lt;p&gt;If the code will be thrown away—POCs, demos, experiments—vibe coding is ideal. Longevity doesn’t matter. Speed does.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hackathons &amp;amp; Side Projects
&lt;/h3&gt;

&lt;p&gt;When the goal is learning or validation, not production stability, &lt;a href="https://nileshblog.tech/vibe-coding-vs-engineering-judgment-why-speed-alone-cant-ship-reliable-software/" rel="noopener noreferrer"&gt;vibe coding&lt;/a&gt; is a net win.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boilerplate &amp;amp; Scaffolding
&lt;/h3&gt;

&lt;p&gt;CRUD APIs, basic UI layouts, config setup—AI handles these well and saves real time.&lt;/p&gt;

&lt;p&gt;In all these cases, the cost of mistakes is low.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Vibe Coding Fails ❌
&lt;/h2&gt;

&lt;p&gt;This is where experience matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Large, Long-Lived Systems
&lt;/h3&gt;

&lt;p&gt;Code that must survive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;multiple teams,&lt;/li&gt;
&lt;li&gt;refactors,&lt;/li&gt;
&lt;li&gt;scaling,&lt;/li&gt;
&lt;li&gt;years of maintenance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI-generated structure often looks clean early and becomes painful later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security-Critical Code
&lt;/h3&gt;

&lt;p&gt;Auth, permissions, payments, secrets.&lt;br&gt;
Vibe coding here is risky because insecure defaults don’t fail loudly—they fail later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Complex Business Logic
&lt;/h3&gt;

&lt;p&gt;Business rules are messy and full of exceptions. AI tends to simplify them incorrectly and encode assumptions that break in edge cases.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Real Mistake I Made Using Vibe Coding
&lt;/h2&gt;

&lt;p&gt;I once used AI to quickly implement a background job flow. It worked perfectly in staging. Clean retries. Nice abstractions.&lt;/p&gt;

&lt;p&gt;What I missed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retries weren’t idempotent,&lt;/li&gt;
&lt;li&gt;partial failures caused duplicate writes,&lt;/li&gt;
&lt;li&gt;logs hid the real issue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It took a production incident to uncover it.&lt;/p&gt;

&lt;p&gt;The AI didn’t make the mistake.&lt;br&gt;
I did—by trusting speed over judgment.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Much Vibe Coding Is Too Much?
&lt;/h2&gt;

&lt;p&gt;A simple rule that works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you can’t explain why the code is safe, you shouldn’t ship it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI can help write code.&lt;br&gt;
Only humans can own the consequences.&lt;/p&gt;

&lt;p&gt;Use AI as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an assistant,&lt;/li&gt;
&lt;li&gt;a drafting tool,&lt;/li&gt;
&lt;li&gt;a productivity multiplier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not as the architect or decision-maker.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security Risks Are the Quiet Problem
&lt;/h2&gt;

&lt;p&gt;The biggest danger of vibe coding isn’t broken code—it’s unquestioned code.&lt;/p&gt;

&lt;p&gt;Common issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hardcoded secrets “temporarily” left in place,&lt;/li&gt;
&lt;li&gt;overly permissive access checks,&lt;/li&gt;
&lt;li&gt;unsafe dependency choices,&lt;/li&gt;
&lt;li&gt;missing validation paths.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything looks fine until it isn’t.&lt;/p&gt;

&lt;p&gt;Security requires skepticism. AI doesn’t have that instinct.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Practices for Safe Vibe Coding
&lt;/h2&gt;

&lt;p&gt;What’s worked for me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slow down at boundaries (auth, data writes, integrations)&lt;/li&gt;
&lt;li&gt;Review AI code as if someone else wrote it&lt;/li&gt;
&lt;li&gt;Ask how it fails, not just how it works&lt;/li&gt;
&lt;li&gt;Never skip human code review&lt;/li&gt;
&lt;li&gt;Treat AI output as untrusted by default&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Speed without discipline just moves problems downstream.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Verdict
&lt;/h2&gt;

&lt;p&gt;Vibe coding isn’t bad.&lt;br&gt;
Blind vibe coding is.&lt;/p&gt;

&lt;p&gt;Use vibe coding to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;explore ideas,&lt;/li&gt;
&lt;li&gt;reduce friction,&lt;/li&gt;
&lt;li&gt;move fast where risk is low.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rely on engineering judgment to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;protect users,&lt;/li&gt;
&lt;li&gt;secure systems,&lt;/li&gt;
&lt;li&gt;design for failure,&lt;/li&gt;
&lt;li&gt;own production outcomes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Speed ships features. Judgment keeps systems alive.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s the difference experience teaches you.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>vibecoding</category>
      <category>software</category>
      <category>discuss</category>
    </item>
    <item>
      <title>How Video Platforms Show Instant Hover Previews Using Sprite Sheets in Node.js</title>
      <dc:creator>Nilesh Raut</dc:creator>
      <pubDate>Mon, 12 Jan 2026 15:07:48 +0000</pubDate>
      <link>https://forem.com/speaklouder/how-video-platforms-show-instant-hover-previews-using-sprite-sheets-in-nodejs-2l0l</link>
      <guid>https://forem.com/speaklouder/how-video-platforms-show-instant-hover-previews-using-sprite-sheets-in-nodejs-2l0l</guid>
      <description>&lt;p&gt;If you’ve ever hovered over a video timeline and seen preview images change instantly, you’ve already interacted with sprite sheets—even if you didn’t know what they were called.&lt;/p&gt;

&lt;p&gt;Those previews aren’t loaded one image at a time. That approach would be slow, expensive, and unreliable once traffic grows. Instead, the application loads &lt;strong&gt;one image&lt;/strong&gt; and reuses it efficiently.&lt;/p&gt;

&lt;p&gt;Sprite sheets are still one of the most practical ways to build &lt;strong&gt;fast, interactive image previews&lt;/strong&gt;, especially for video platforms, dashboards, and media-heavy applications where user interaction needs to feel instant.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Real-World Example: Video Timeline Hover
&lt;/h2&gt;

&lt;p&gt;Think about how video platforms handle timeline previews.&lt;/p&gt;

&lt;p&gt;As you move your cursor across the progress bar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;preview frames update immediately,&lt;/li&gt;
&lt;li&gt;there’s no visible loading,&lt;/li&gt;
&lt;li&gt;network activity doesn’t spike.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What’s happening behind the scenes is simple and effective. The frontend loads a &lt;strong&gt;single &lt;a href="https://nileshblog.tech/sprite-sheets-in-node-js-how-video-platforms-show-fast-hover-previews-without-loading-hundreds-of-images/" rel="noopener noreferrer"&gt;sprite sheet &lt;/a&gt;image&lt;/strong&gt; ahead of time. As the user scrubs through the timeline, the UI just changes which part of that image is visible. After the initial load, the network is no longer involved.&lt;/p&gt;

&lt;p&gt;That’s why the interaction feels smooth and predictable.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a Sprite Sheet Actually Is
&lt;/h2&gt;

&lt;p&gt;A sprite sheet is a &lt;strong&gt;single image that contains many smaller images arranged in a grid&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s an example of a real sprite sheet generated from a video, showing how multiple preview frames are packed into a single image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpmk9ov413yb7qfntyjnv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpmk9ov413yb7qfntyjnv.png" alt="Sprite sheet containing video preview thumbnails generated from a video" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of loading multiple files like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;thumb_01.jpg
thumb_02.jpg
thumb_03.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the application loads:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spritesheet.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontend then displays only the relevant section of that image using simple position calculations. No additional image requests are required during interaction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Sprite Sheets Still Matter
&lt;/h2&gt;

&lt;p&gt;Even with HTTP/2, CDNs, and faster networks, sprite sheets solve problems that haven’t gone away:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;they drastically reduce the number of image requests,&lt;/li&gt;
&lt;li&gt;hover interactions feel instant,&lt;/li&gt;
&lt;li&gt;backend load stays predictable,&lt;/li&gt;
&lt;li&gt;caching works extremely well.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For interactive previews, removing the network from the critical interaction path makes a noticeable difference in user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefjp0q6mt0g0gm1mwadh.webp" alt="Flow diagram of example sprite sheet" width="800" height="533"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Backend Responsibilities (Node.js)
&lt;/h2&gt;

&lt;p&gt;The backend should &lt;strong&gt;never&lt;/strong&gt; generate preview images on demand.&lt;/p&gt;

&lt;p&gt;In a production setup, the backend is responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;generating &lt;a href="https://nileshblog.tech/sprite-sheets-in-node-js-how-video-platforms-show-fast-hover-previews-without-loading-hundreds-of-images/" rel="noopener noreferrer"&gt;sprite sheets&lt;/a&gt; asynchronously,&lt;/li&gt;
&lt;li&gt;storing them as static assets,&lt;/li&gt;
&lt;li&gt;exposing metadata that describes how the sprite sheet is structured.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sprite generation typically runs in background jobs or media pipelines, not inside API request handlers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Sprite Metadata
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"spriteUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/sprites/video_101.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"frameWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"frameHeight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"columns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rows"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"intervalSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This metadata is what allows the frontend to correctly calculate which frame to show at any given time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Simple Node.js Backend Example
&lt;/h2&gt;

&lt;p&gt;Here’s a minimal Express setup that exposes sprite metadata and serves the sprite image as a static asset.&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;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&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;sharp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sharp&lt;/span&gt;&lt;span class="dl"&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&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="s2"&gt;/sprites&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sprites&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// Upload video to generate the sprites sheet of that image &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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/upload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;single&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video&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;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;videoPath&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&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;videoName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;originalname&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;name&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;thumbnailsDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`thumbnails/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;videoName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;spriteOutput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`sprites/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;videoName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.jpg`&lt;/span&gt;&lt;span class="p"&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;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;thumbnailsDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// 1. Extract frames every 2 seconds&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;extractCmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
    ffmpeg -i &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;videoPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; -vf fps=1/2 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;thumbnailsDir&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/thumb_%03d.jpg
  `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extractCmd&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Frame extraction failed:&lt;/span&gt;&lt;span class="dl"&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="k"&gt;return&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;files&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;readdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;thumbnailsDir&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;frameWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;160&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;frameHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;90&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;columns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&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;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;columns&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;spriteWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;frameWidth&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;columns&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;spriteHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;frameHeight&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;rows&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;compositeImages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&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;col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;columns&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;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;thumbnailsDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;col&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;frameWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;frameHeight&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sharp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;spriteWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;spriteHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;channels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#000&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;span class="nf"&gt;composite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compositeImages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;jpeg&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spriteOutput&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="s2"&gt;Sprite sheet created:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spriteOutput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Store the generated sprite sheet in object storage (e.g. S3, GCS)&lt;/span&gt;
&lt;span class="c1"&gt;// and save the sprite URL + frame metadata with the video record&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;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Video uploaded successfully. Sprite generation started.&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;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="s2"&gt;/api/video/:id/sprite&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;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="c1"&gt;//add your own logic to how to acces the new genrated image eg store in to s3 storage any where and return the url of image &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;spriteUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/sprites/video_101.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;frameWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;frameHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;intervalSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="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;listen&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="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="s2"&gt;Server running on port 3000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach scales cleanly because the backend only serves metadata and static files. The heavy work happens elsewhere.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frontend Handling (Plain JavaScript)
&lt;/h2&gt;

&lt;p&gt;On the frontend, the logic is straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;fetch the sprite metadata,&lt;/li&gt;
&lt;li&gt;load the sprite image once,&lt;/li&gt;
&lt;li&gt;update the visible frame based on cursor position.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  HTML
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"timeline"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"preview"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  JavaScript
&lt;/h3&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;preview&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preview&lt;/span&gt;&lt;span class="dl"&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;timeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;timeline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/video/101/sprite&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="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="nx"&gt;data&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;preview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backgroundImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`url(&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="nx"&gt;spriteUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;;&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;frameWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;frameHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;intervalSeconds&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mousemove&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;e&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;rect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBoundingClientRect&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;percent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientX&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&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;videoDuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// seconds&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hoverTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;percent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;videoDuration&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;frameIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hoverTime&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;intervalSeconds&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;col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;frameIndex&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;columns&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;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frameIndex&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backgroundPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="s2"&gt;`-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;col&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;frameWidth&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px -&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;frameHeight&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px`&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;Once the sprite image is loaded, preview updates happen entirely on the client, with no additional network calls.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;p&gt;Some issues show up repeatedly in real projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;generating sprite sheets synchronously in API requests,&lt;/li&gt;
&lt;li&gt;hardcoding frame sizes on the frontend,&lt;/li&gt;
&lt;li&gt;creating very large sprite sheets that hurt mobile performance,&lt;/li&gt;
&lt;li&gt;treating sprite sheets as a frontend-only concern.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sprite sheets work best when &lt;strong&gt;&lt;a href="https://nileshblog.tech/sprite-sheets-in-node-js-how-video-platforms-show-fast-hover-previews-without-loading-hundreds-of-images/" rel="noopener noreferrer"&gt;backend&lt;/a&gt; and frontend agree on a clear contract&lt;/strong&gt;.&lt;/p&gt;




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

&lt;p&gt;Sprite sheets aren’t outdated or hacky. They’re a practical performance pattern that still works because it removes the network from user interactions.&lt;/p&gt;

&lt;p&gt;If you’re building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;video players,&lt;/li&gt;
&lt;li&gt;hover previews,&lt;/li&gt;
&lt;li&gt;timeline scrubbing features,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;sprite sheets remain one of the cleanest solutions available when implemented intentionally.&lt;/p&gt;

&lt;p&gt;I write more content like this on &lt;a href="https://nileshblog.tech/" rel="noopener noreferrer"&gt;nileshblog.tech&lt;/a&gt; if you want to explore further.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>software</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Designing APIs That Are Hard to Misuse</title>
      <dc:creator>Nilesh Raut</dc:creator>
      <pubDate>Sat, 10 Jan 2026 18:30:00 +0000</pubDate>
      <link>https://forem.com/speaklouder/designing-apis-that-are-hard-to-misuse-5d6b</link>
      <guid>https://forem.com/speaklouder/designing-apis-that-are-hard-to-misuse-5d6b</guid>
      <description>&lt;p&gt;Most backend bugs don’t happen because developers are careless.&lt;br&gt;
They happen because &lt;strong&gt;APIs are easy to misuse&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If an API allows the wrong thing, someone will eventually do it — intentionally or not. Senior engineers know this, and they design APIs that &lt;strong&gt;guide correct usage and make incorrect usage difficult&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This post is about how experienced engineers think when designing APIs that survive real-world use.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Core Principle: Assume Misuse, Not Malice
&lt;/h2&gt;

&lt;p&gt;When &lt;a href="https://nileshblog.tech/designing-apis-that-are-hard-to-misuse/" rel="noopener noreferrer"&gt;designing an API&lt;/a&gt;, don’t assume:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;consumers will read the docs carefully,&lt;/li&gt;
&lt;li&gt;inputs will always be valid,&lt;/li&gt;
&lt;li&gt;calls will be made in the correct order.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Assume instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;someone will misunderstand it,&lt;/li&gt;
&lt;li&gt;someone will skip validation,&lt;/li&gt;
&lt;li&gt;someone will copy-paste an example without thinking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A good API doesn’t rely on “being used correctly.”&lt;br&gt;
It &lt;strong&gt;enforces correctness by design&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Clear Inputs, Clear Outputs
&lt;/h2&gt;

&lt;p&gt;Ambiguous APIs invite misuse.&lt;/p&gt;

&lt;p&gt;Bad example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/updateUser&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What does this update?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name?&lt;/li&gt;
&lt;li&gt;email?&lt;/li&gt;
&lt;li&gt;password?&lt;/li&gt;
&lt;li&gt;all of them?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Better:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;PATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/users/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;/email&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the intent is clear,&lt;/li&gt;
&lt;li&gt;the scope is limited,&lt;/li&gt;
&lt;li&gt;misuse becomes harder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If an API endpoint can do “too many things,” it will eventually do the wrong one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Make Invalid States Impossible
&lt;/h2&gt;

&lt;p&gt;Senior engineers try to design APIs where &lt;strong&gt;invalid states cannot exist&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"deleted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Design it so:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a user cannot be both active and deleted,&lt;/li&gt;
&lt;li&gt;the API does not accept conflicting inputs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your API allows contradictory data, the bug isn’t in the client — it’s in the design.&lt;/p&gt;




&lt;h2&gt;
  
  
  Use Explicit Errors, Not Silent Defaults
&lt;/h2&gt;

&lt;p&gt;Silent behavior is dangerous.&lt;/p&gt;

&lt;p&gt;Bad design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing field → default value applied&lt;/li&gt;
&lt;li&gt;invalid input → ignored&lt;/li&gt;
&lt;li&gt;partial failure → success response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes bugs invisible.&lt;/p&gt;

&lt;p&gt;Better design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reject invalid input loudly,&lt;/li&gt;
&lt;li&gt;return clear error messages,&lt;/li&gt;
&lt;li&gt;fail fast and early.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;APIs should &lt;strong&gt;teach consumers how to use them correctly&lt;/strong&gt; through errors.&lt;/p&gt;




&lt;h2&gt;
  
  
  Avoid “Magic” Behavior
&lt;/h2&gt;

&lt;p&gt;Magic APIs feel convenient at first — and painful later.&lt;/p&gt;

&lt;p&gt;Examples of magic behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;auto-creating resources without saying so,&lt;/li&gt;
&lt;li&gt;silently retrying without limits,&lt;/li&gt;
&lt;li&gt;changing behavior based on hidden flags.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If something important happens, make it explicit.&lt;/p&gt;

&lt;p&gt;Good APIs are boring.&lt;br&gt;
Boring APIs are predictable.&lt;/p&gt;


&lt;h2&gt;
  
  
  Idempotency Matters More Than You Think
&lt;/h2&gt;

&lt;p&gt;In real systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;requests get retried,&lt;/li&gt;
&lt;li&gt;clients time out,&lt;/li&gt;
&lt;li&gt;networks fail.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If calling an API twice causes unintended side effects, it will break in production.&lt;/p&gt;

&lt;p&gt;Design APIs so:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;repeated requests are safe,&lt;/li&gt;
&lt;li&gt;duplicate calls don’t corrupt state,&lt;/li&gt;
&lt;li&gt;clients don’t need complex retry logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This alone prevents many production incidents.&lt;/p&gt;


&lt;h2&gt;
  
  
  Design for the Future Consumer
&lt;/h2&gt;

&lt;p&gt;The person using your API in six months:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;might not be you,&lt;/li&gt;
&lt;li&gt;might not know the context,&lt;/li&gt;
&lt;li&gt;might be under pressure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can this API be misunderstood?&lt;/li&gt;
&lt;li&gt;Can it be called in the wrong order?&lt;/li&gt;
&lt;li&gt;Can misuse cause data corruption?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the answer is “yes,” redesign.&lt;/p&gt;


&lt;h2&gt;
  
  
  A Real-World Example
&lt;/h2&gt;

&lt;p&gt;Many production bugs come from APIs like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/processPayment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Called twice → double charge.&lt;/p&gt;

&lt;p&gt;A better design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;separate intent from execution,&lt;/li&gt;
&lt;li&gt;require idempotency keys,&lt;/li&gt;
&lt;li&gt;make side effects explicit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The extra effort up front saves incidents later.&lt;br&gt;
&lt;a href="https://nileshblog.tech/" rel="noopener noreferrer"&gt;🔗 Check out our blog site for more: nileshblog.tech&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Takeaway
&lt;/h2&gt;

&lt;p&gt;APIs are contracts, not just endpoints.&lt;/p&gt;

&lt;p&gt;A well-designed API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;limits what can go wrong,&lt;/li&gt;
&lt;li&gt;makes correct usage obvious,&lt;/li&gt;
&lt;li&gt;makes incorrect usage difficult,&lt;/li&gt;
&lt;li&gt;protects the system from human error.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Senior engineers don’t just design APIs that work —&lt;br&gt;
they design APIs that &lt;strong&gt;are hard to misuse&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>architecture</category>
      <category>api</category>
      <category>design</category>
    </item>
    <item>
      <title>Stateless vs Stateful Services</title>
      <dc:creator>Nilesh Raut</dc:creator>
      <pubDate>Tue, 06 Jan 2026 18:30:00 +0000</pubDate>
      <link>https://forem.com/speaklouder/stateless-vs-stateful-services-3o7l</link>
      <guid>https://forem.com/speaklouder/stateless-vs-stateful-services-3o7l</guid>
      <description>&lt;p&gt;This is one of those backend topics everyone &lt;em&gt;thinks&lt;/em&gt; they understand — until production proves otherwise.&lt;/p&gt;

&lt;p&gt;On paper, stateless sounds “better.”&lt;br&gt;
In reality, both &lt;a href="https://nileshblog.tech/stateless-vs-stateful-services-with-real-examples/" rel="noopener noreferrer"&gt;stateless and stateful&lt;/a&gt; services exist for good reasons. Problems start when we &lt;strong&gt;pick one without understanding the trade-offs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s break this down the way it actually shows up in real systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Does “Stateless” Really Mean?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;stateless service&lt;/strong&gt; does &lt;strong&gt;not store client-specific data between requests&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Each request:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is independent&lt;/li&gt;
&lt;li&gt;Contains everything the server needs&lt;/li&gt;
&lt;li&gt;Can be handled by &lt;em&gt;any&lt;/em&gt; instance&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Simple Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /users/123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads user data from a database&lt;/li&gt;
&lt;li&gt;Returns the response&lt;/li&gt;
&lt;li&gt;Forgets everything about the request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No memory of who you are. No session stored on the server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;REST APIs&lt;/li&gt;
&lt;li&gt;Public HTTP services&lt;/li&gt;
&lt;li&gt;Authentication using JWT tokens&lt;/li&gt;
&lt;li&gt;Read-heavy backend services&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What Does “Stateful” Actually Mean?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;stateful service&lt;/strong&gt; &lt;strong&gt;remembers something about the client&lt;/strong&gt; between requests.&lt;/p&gt;

&lt;p&gt;That “state” could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Session data&lt;/li&gt;
&lt;li&gt;In-memory cache&lt;/li&gt;
&lt;li&gt;User progress&lt;/li&gt;
&lt;li&gt;Open connections&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Simple Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Login → Session created → Session reused on next request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server &lt;em&gt;remembers you&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Login sessions stored in memory&lt;/li&gt;
&lt;li&gt;WebSocket connections&lt;/li&gt;
&lt;li&gt;Multiplayer game servers&lt;/li&gt;
&lt;li&gt;In-memory queues&lt;/li&gt;
&lt;li&gt;Stateful stream processors&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Key Difference (In One Line)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stateless&lt;/strong&gt; → “Every request is new.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateful&lt;/strong&gt; → “I remember you.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That single difference impacts &lt;strong&gt;scaling, reliability, and debugging&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Stateless Services Are Easier to Scale
&lt;/h2&gt;

&lt;p&gt;Stateless services scale beautifully.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any instance can handle any request&lt;/li&gt;
&lt;li&gt;Load balancers don’t care where traffic goes&lt;/li&gt;
&lt;li&gt;Crashed instances don’t lose user data&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;You have 5 backend servers behind a load balancer.&lt;/p&gt;

&lt;p&gt;If one goes down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traffic shifts to others&lt;/li&gt;
&lt;li&gt;No user impact&lt;/li&gt;
&lt;li&gt;No recovery logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why stateless services dominate modern backend design.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Stateful Services Still Exist (And Always Will)
&lt;/h2&gt;

&lt;p&gt;Despite the hype, stateless is &lt;strong&gt;not always the right choice&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Stateful services exist because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some data is expensive to recompute&lt;/li&gt;
&lt;li&gt;Some interactions require continuity&lt;/li&gt;
&lt;li&gt;Some systems depend on long-lived connections&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: WebSockets
&lt;/h3&gt;

&lt;p&gt;A chat server maintains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open connections&lt;/li&gt;
&lt;li&gt;Message state&lt;/li&gt;
&lt;li&gt;User presence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trying to make that fully stateless often makes things worse, not better.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real Production Example: Session Handling
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Stateful (Problematic)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Session stored in server memory&lt;/li&gt;
&lt;li&gt;User logs in&lt;/li&gt;
&lt;li&gt;Load balancer sends next request to another server&lt;/li&gt;
&lt;li&gt;Session not found → user logged out&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This breaks immediately at scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Better Approach
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stateless backend&lt;/li&gt;
&lt;li&gt;Session stored in Redis or DB&lt;/li&gt;
&lt;li&gt;Any instance can validate session&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You still have &lt;em&gt;state&lt;/em&gt;, but it’s &lt;strong&gt;externalized&lt;/strong&gt;, not tied to a single instance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Mistake: Confusing “Stateless” With “No State”
&lt;/h2&gt;

&lt;p&gt;Stateless does &lt;strong&gt;not&lt;/strong&gt; mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No database&lt;/li&gt;
&lt;li&gt;No cache&lt;/li&gt;
&lt;li&gt;No user data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The service instance does not own the state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The state lives somewhere else.&lt;/p&gt;




&lt;h2&gt;
  
  
  Debugging Differences (Very Real)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Stateless Debugging
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easier reproduction&lt;/li&gt;
&lt;li&gt;Restart fixes many issues&lt;/li&gt;
&lt;li&gt;Horizontal scaling is safe&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Stateful Debugging
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Bugs depend on order of requests&lt;/li&gt;
&lt;li&gt;Restart may lose critical data&lt;/li&gt;
&lt;li&gt;Harder to reproduce locally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why stateful bugs feel “random” in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Stateless Is the Right Choice
&lt;/h2&gt;

&lt;p&gt;Use stateless services when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’re building HTTP APIs&lt;/li&gt;
&lt;li&gt;You expect traffic spikes&lt;/li&gt;
&lt;li&gt;You need easy horizontal scaling&lt;/li&gt;
&lt;li&gt;You want safer deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re unsure, &lt;strong&gt;default to stateless&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Stateful Is the Right Choice
&lt;/h2&gt;

&lt;p&gt;Stateful services make sense when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need real-time connections&lt;/li&gt;
&lt;li&gt;You maintain long-lived sessions&lt;/li&gt;
&lt;li&gt;Performance depends on in-memory state&lt;/li&gt;
&lt;li&gt;The cost of externalizing state is too high&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key is being &lt;em&gt;intentional&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nileshblog.tech/stateless-vs-stateful-services-with-real-examples/" rel="noopener noreferrer"&gt;Stateless vs stateful&lt;/a&gt; is not a debate — it’s a design decision.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stateless services optimize for &lt;strong&gt;scalability and resilience&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Stateful services optimize for &lt;strong&gt;continuity and performance&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most modern systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep services stateless&lt;/li&gt;
&lt;li&gt;Push state to databases, caches, or message systems&lt;/li&gt;
&lt;li&gt;Accept statefulness only where it truly adds value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you understand this distinction clearly, you’ll avoid a whole class of backend failures before they ever reach production.&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>backend</category>
      <category>microservices</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How to Review AI-Written Code Like a Engineer</title>
      <dc:creator>Nilesh Raut</dc:creator>
      <pubDate>Sat, 03 Jan 2026 05:56:39 +0000</pubDate>
      <link>https://forem.com/speaklouder/how-to-review-ai-written-code-like-a-engineer-1f4g</link>
      <guid>https://forem.com/speaklouder/how-to-review-ai-written-code-like-a-engineer-1f4g</guid>
      <description>&lt;p&gt;AI can generate code incredibly fast.&lt;br&gt;
Sometimes fast enough to make you pause and think, &lt;em&gt;“Did this just replace half my work?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But speed has never been the hard part of engineering.&lt;/p&gt;

&lt;p&gt;The real challenge is making sure the code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;does the right thing,&lt;/li&gt;
&lt;li&gt;fails safely,&lt;/li&gt;
&lt;li&gt;can be understood later,&lt;/li&gt;
&lt;li&gt;and won’t hurt you in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s why reviewing AI-written code requires a slightly different mindset than reviewing human code. The mistakes are subtler, the confidence is misleading, and the risks are easy to underestimate.&lt;/p&gt;

&lt;p&gt;This post walks through &lt;strong&gt;how engineers actually review AI-generated code in real projects&lt;/strong&gt; — not in demos, not in theory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start With the Right Mindset
&lt;/h2&gt;

&lt;p&gt;The most important rule is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treat AI-written code as a first draft, not a solution.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It may compile.&lt;br&gt;
It may pass basic tests.&lt;br&gt;
It may even look clean.&lt;/p&gt;

&lt;p&gt;That doesn’t mean it’s correct, safe, or appropriate for your system.&lt;/p&gt;

&lt;p&gt;engineers don’t ask &lt;em&gt;“Does this work?”&lt;/em&gt;&lt;br&gt;
They ask &lt;em&gt;“Should this exist in this form?”&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Understand the Intent Before the Code
&lt;/h2&gt;

&lt;p&gt;Before reading the implementation, step back and ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What problem is this code supposed to solve?&lt;/li&gt;
&lt;li&gt;What are the inputs and expected outputs?&lt;/li&gt;
&lt;li&gt;What guarantees does it claim to provide?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This matters because AI often solves &lt;strong&gt;the prompt&lt;/strong&gt;, not the real requirement.&lt;/p&gt;

&lt;p&gt;If you can’t explain the intent clearly in your own words, reviewing the code line by line is pointless. Misaligned intent leads to clean-looking but wrong solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Think About Failure, Not Success
&lt;/h2&gt;

&lt;p&gt;AI code usually handles the happy path well.&lt;br&gt;
That’s not where production issues come from.&lt;/p&gt;

&lt;p&gt;Ask questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happens with empty or invalid input?&lt;/li&gt;
&lt;li&gt;What happens under load?&lt;/li&gt;
&lt;li&gt;What happens when a dependency slows down or fails?&lt;/li&gt;
&lt;li&gt;What happens if this function is called in an unexpected order?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;engineers always look for &lt;strong&gt;failure modes first&lt;/strong&gt;. If the code has no obvious way to fail, that’s usually a bad sign.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Look for Silent Assumptions
&lt;/h2&gt;

&lt;p&gt;AI is very good at making assumptions — and very bad at documenting them.&lt;/p&gt;

&lt;p&gt;Common ones include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This value is never null&lt;/li&gt;
&lt;li&gt;This list is always sorted&lt;/li&gt;
&lt;li&gt;This function is only called once&lt;/li&gt;
&lt;li&gt;This service is always fast&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any time the logic depends on something &lt;em&gt;always&lt;/em&gt; being true, stop and verify where that guarantee comes from. Many real production bugs are just assumptions that stopped being true over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Review Security Before Style 🔐
&lt;/h2&gt;

&lt;p&gt;Clean code doesn’t matter if it’s unsafe.&lt;/p&gt;

&lt;p&gt;Before commenting on formatting or naming, check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are authorization checks present?&lt;/li&gt;
&lt;li&gt;Is user input validated?&lt;/li&gt;
&lt;li&gt;Is sensitive data protected?&lt;/li&gt;
&lt;li&gt;Are defaults safe?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI-generated code often looks professional while quietly skipping security boundaries. If the code touches authentication, payments, or user data, it deserves extra scrutiny.&lt;/p&gt;

&lt;p&gt;Security issues are expensive because they don’t always fail loudly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Check the Level of Complexity
&lt;/h2&gt;

&lt;p&gt;AI tends to either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;over-engineer simple problems, or&lt;/li&gt;
&lt;li&gt;under-engineer complex ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unnecessary abstractions,&lt;/li&gt;
&lt;li&gt;premature generalization,&lt;/li&gt;
&lt;li&gt;hardcoded behavior that limits future change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ask yourself: &lt;em&gt;Is this complexity solving a real problem today, or just adding mental overhead?&lt;/em&gt;&lt;br&gt;
engineers value clarity over cleverness.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Read It Like You’ll Own It Long-Term
&lt;/h2&gt;

&lt;p&gt;A useful mental trick is to ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Would I be comfortable debugging this at 2 AM?&lt;/li&gt;
&lt;li&gt;Would a new teammate understand this without context?&lt;/li&gt;
&lt;li&gt;Are names honest and specific?&lt;/li&gt;
&lt;li&gt;Are side effects obvious?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI code often uses generic naming and hides behavior in ways that feel fine at first but become painful later. If something feels hard to reason about now, it will only get worse with time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: Check Observability
&lt;/h2&gt;

&lt;p&gt;When this code fails in production, how will you know?&lt;/p&gt;

&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;meaningful logs,&lt;/li&gt;
&lt;li&gt;useful error messages,&lt;/li&gt;
&lt;li&gt;signals that point to the real problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Silent failures are dangerous. Good code doesn’t just fail — it explains why.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 8: Don’t Trust Without Tests
&lt;/h2&gt;

&lt;p&gt;Never approve AI-written code without tests.&lt;/p&gt;

&lt;p&gt;Check whether tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cover edge cases,&lt;/li&gt;
&lt;li&gt;assert behavior instead of implementation,&lt;/li&gt;
&lt;li&gt;fail for the right reasons.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tests are not just about correctness — they’re future documentation for how this code is expected to behave when things go wrong.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 9: Decide What to Keep and What to Rewrite
&lt;/h2&gt;

&lt;p&gt;engineers don’t treat AI output as all-or-nothing.&lt;/p&gt;

&lt;p&gt;Often the best outcome is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep the structure,&lt;/li&gt;
&lt;li&gt;rewrite critical logic,&lt;/li&gt;
&lt;li&gt;simplify what doesn’t need to be clever.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI is a productivity accelerator, not an authority. You’re still responsible for the final shape of the code.&lt;/p&gt;




&lt;p&gt;🔗 &lt;a href="https://nileshblog.tech/how-to-review-ai-written-code-like-a-senior-engineer/" rel="noopener noreferrer"&gt;Read the full write-up on reviewing AI-written code like a engineer&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Rule of Thumb
&lt;/h2&gt;

&lt;p&gt;Many experienced engineers follow something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI for scaffolding → ✅&lt;/li&gt;
&lt;li&gt;AI for non-critical logic → ⚠️&lt;/li&gt;
&lt;li&gt;AI for security-sensitive paths → ❌ without deep review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The more critical the code, the more human ownership it requires.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Skill Matters More Every Year
&lt;/h2&gt;

&lt;p&gt;As AI writes more code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;codebases grow faster,&lt;/li&gt;
&lt;li&gt;context becomes thinner,&lt;/li&gt;
&lt;li&gt;risk increases quietly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The engineers who stand out won’t be the ones who generate the most code. They’ll be the ones who can look at confident-looking solutions and say, &lt;em&gt;“This feels right, but it’s actually wrong.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That’s judgment.&lt;/p&gt;




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

&lt;p&gt;AI doesn’t remove responsibility — it concentrates it.&lt;/p&gt;

&lt;p&gt;If you approve &lt;a href="https://nileshblog.tech/how-to-review-ai-written-code-like-a-senior-engineer/" rel="noopener noreferrer"&gt;AI-written code&lt;/a&gt;, you own it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;in production,&lt;/li&gt;
&lt;li&gt;during incidents,&lt;/li&gt;
&lt;li&gt;in audits,&lt;/li&gt;
&lt;li&gt;and in postmortems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Review it carefully.&lt;br&gt;
Question it calmly.&lt;br&gt;
Improve it deliberately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI can help you write code faster.&lt;br&gt;
Engineering judgment is what makes it safe.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>software</category>
      <category>vibecoding</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why Debugging Skills Matter More Than Writing New Code</title>
      <dc:creator>Nilesh Raut</dc:creator>
      <pubDate>Sat, 27 Dec 2025 10:34:45 +0000</pubDate>
      <link>https://forem.com/speaklouder/why-debugging-skills-matter-more-than-writing-new-code-2lc7</link>
      <guid>https://forem.com/speaklouder/why-debugging-skills-matter-more-than-writing-new-code-2lc7</guid>
      <description>&lt;h3&gt;
  
  
  The Moment Every Developer Recognizes
&lt;/h3&gt;

&lt;p&gt;Writing new code feels productive.&lt;br&gt;
Debugging feels slow, frustrating, and invisible.&lt;/p&gt;

&lt;p&gt;Yet the most stressful moments in a developer’s career rarely involve writing something new. They involve a system that &lt;em&gt;already exists&lt;/em&gt; and is behaving in ways no one expected.&lt;/p&gt;

&lt;p&gt;Production doesn’t break because of missing features.&lt;br&gt;
It breaks because of misunderstood ones.&lt;/p&gt;


&lt;h2&gt;
  
  
  New Code Is Easy. Broken Code Is Reality.
&lt;/h2&gt;

&lt;p&gt;Most developers are trained to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build features&lt;/li&gt;
&lt;li&gt;Follow patterns&lt;/li&gt;
&lt;li&gt;Write clean abstractions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But real-world systems are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stateful&lt;/li&gt;
&lt;li&gt;Distributed&lt;/li&gt;
&lt;li&gt;Full of edge cases&lt;/li&gt;
&lt;li&gt;Running code written by many people over many years&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At some point, every engineer realizes that &lt;strong&gt;writing new code is a smaller part of the job than keeping existing code working&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Debugging Is How You Learn the System
&lt;/h2&gt;

&lt;p&gt;Debugging forces you to answer uncomfortable questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why does this exist?&lt;/li&gt;
&lt;li&gt;What assumptions were made?&lt;/li&gt;
&lt;li&gt;What happens if this fails?&lt;/li&gt;
&lt;li&gt;Who depends on this behavior?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can write new code without understanding the system.&lt;br&gt;
You cannot debug effectively without understanding it.&lt;/p&gt;

&lt;p&gt;That’s why great debuggers ramp up faster on new teams — they learn the system by following its failures.&lt;/p&gt;


&lt;h2&gt;
  
  
  Debugging Builds Engineering Intuition
&lt;/h2&gt;

&lt;p&gt;Over time, debugging teaches you patterns you can’t get from tutorials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Race conditions&lt;/li&gt;
&lt;li&gt;Partial failures&lt;/li&gt;
&lt;li&gt;Misconfigured environments&lt;/li&gt;
&lt;li&gt;“Works locally” production bugs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Strong debuggers don’t panic when things break.&lt;br&gt;
They form hypotheses, test them, and narrow the problem space.&lt;/p&gt;

&lt;p&gt;That mindset matters more than syntax mastery.&lt;/p&gt;


&lt;h2&gt;
  
  
  Production Doesn’t Care How Clean Your Code Is
&lt;/h2&gt;

&lt;p&gt;In production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logs lie or are missing&lt;/li&gt;
&lt;li&gt;Metrics are noisy&lt;/li&gt;
&lt;li&gt;Errors cascade&lt;/li&gt;
&lt;li&gt;Small changes cause large failures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Debugging teaches you how systems behave under stress.&lt;/p&gt;

&lt;p&gt;This is why senior engineers are often pulled into incidents — not because they write faster, but because they &lt;strong&gt;reason better when things go wrong&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Debugging Improves Your Future Code
&lt;/h2&gt;

&lt;p&gt;Developers who debug a lot start writing different code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better logs&lt;/li&gt;
&lt;li&gt;Clearer error messages&lt;/li&gt;
&lt;li&gt;Safer defaults&lt;/li&gt;
&lt;li&gt;Fewer assumptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Debugging feedback loops improve design.&lt;/p&gt;

&lt;p&gt;If you never feel the pain of broken code, you don’t learn how to prevent it.&lt;/p&gt;



&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://nileshblog.tech/why-debugging-skills-matter-more-than-writing-new-code/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnileshblog.tech%2Fwp-content%2Fuploads%2F2025%2F12%2FWhy-Debugging-Skills-Matter-More-Than-Writing-New-Code.webp" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://nileshblog.tech/why-debugging-skills-matter-more-than-writing-new-code/" rel="noopener noreferrer" class="c-link"&gt;
            Why Debugging Skills Matter More Than Writing New Code : NileshBlog.Tech
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Debugging skills matter more than writing new code. Learn why real-world production issues, war stories, and a practical checklist shape better software engineers.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnileshblog.tech%2Fwp-content%2Fuploads%2F2023%2F11%2FNileshblog.tech-logo-1-96x96.png"&gt;
          nileshblog.tech
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




&lt;h2&gt;
  
  
  Why Debugging Skills Age Better Than Languages
&lt;/h2&gt;

&lt;p&gt;Languages change.&lt;br&gt;
Frameworks come and go.&lt;br&gt;
Tooling evolves constantly.&lt;/p&gt;

&lt;p&gt;But debugging skills transfer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Across languages&lt;/li&gt;
&lt;li&gt;Across stacks&lt;/li&gt;
&lt;li&gt;Across companies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read logs&lt;/li&gt;
&lt;li&gt;Trace execution&lt;/li&gt;
&lt;li&gt;Understand failure modes&lt;/li&gt;
&lt;li&gt;Ask the right questions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can survive almost any tech stack.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://nileshblog.tech/why-debugging-skills-matter-more-than-writing-new-code/%20this%20just%20gave%20me%20title%20where%20to%20add%20in%20dev.to%20post"&gt;Read the full article with real production war stories and a debugging checklist&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Real Career Difference
&lt;/h2&gt;

&lt;p&gt;Junior engineers often ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“What should I learn next?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My honest answer is rarely a new framework.&lt;/p&gt;

&lt;p&gt;It’s:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn how to debug production issues&lt;/li&gt;
&lt;li&gt;Learn how to read logs and metrics&lt;/li&gt;
&lt;li&gt;Learn how to reason about failures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those skills compound over time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Writing Code Feels Like Progress. Debugging &lt;em&gt;Is&lt;/em&gt; Progress.
&lt;/h2&gt;

&lt;p&gt;New code gets attention.&lt;br&gt;
Debugging gets results.&lt;/p&gt;

&lt;p&gt;Great engineers aren’t defined by how much code they write — but by how reliably they can fix what’s already running.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;If you want to grow faster as a developer, stop optimizing for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writing more code&lt;/li&gt;
&lt;li&gt;Learning more frameworks&lt;/li&gt;
&lt;li&gt;Shipping faster at any cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start optimizing for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding failures&lt;/li&gt;
&lt;li&gt;Investigating weird behavior&lt;/li&gt;
&lt;li&gt;Debugging calmly under pressure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Debugging is where real engineering skill shows up.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>software</category>
      <category>programming</category>
      <category>learning</category>
      <category>debug</category>
    </item>
    <item>
      <title>How Much DevOps Knowledge Is Actually Required for an SDE?</title>
      <dc:creator>Nilesh Raut</dc:creator>
      <pubDate>Mon, 22 Dec 2025 18:30:00 +0000</pubDate>
      <link>https://forem.com/speaklouder/how-much-devops-knowledge-is-actually-required-for-an-sde-4jon</link>
      <guid>https://forem.com/speaklouder/how-much-devops-knowledge-is-actually-required-for-an-sde-4jon</guid>
      <description>&lt;h3&gt;
  
  
  The Question Every Developer Eventually Asks
&lt;/h3&gt;

&lt;p&gt;At some point in your career, it happens.&lt;/p&gt;

&lt;p&gt;Your code works locally.&lt;br&gt;
Tests pass.&lt;br&gt;
The PR gets approved.&lt;/p&gt;

&lt;p&gt;Then someone says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“It broke in production.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Suddenly you’re staring at logs, pipelines, dashboards, YAML files, and thinking:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Wait… how much DevOps am I actually expected to know as an SDE?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This question comes up constantly. As teams move faster and ownership shifts left, the line between dev and ops keeps getting blurrier. The short answer: &lt;em&gt;more than before, less than a DevOps engineer.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The long answer is where real-world experience matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Old Model vs. Today’s Reality
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Old World (Mostly Gone)
&lt;/h3&gt;

&lt;p&gt;Earlier, responsibilities were clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers wrote code&lt;/li&gt;
&lt;li&gt;Ops deployed and ran it&lt;/li&gt;
&lt;li&gt;Production issues were “someone else’s problem”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That worked when releases were slow and systems were simpler.&lt;/p&gt;

&lt;h3&gt;
  
  
  The World We Actually Work In
&lt;/h3&gt;

&lt;p&gt;Today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CI/CD is automatic&lt;/li&gt;
&lt;li&gt;Systems are distributed&lt;/li&gt;
&lt;li&gt;Failures are expected&lt;/li&gt;
&lt;li&gt;Teams own services end to end&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if your title says &lt;strong&gt;Software Development Engineer&lt;/strong&gt;, production doesn’t care.&lt;/p&gt;




&lt;h2&gt;
  
  
  What DevOps Knowledge Is &lt;em&gt;Not&lt;/em&gt; Required
&lt;/h2&gt;

&lt;p&gt;Let’s clear some confusion.&lt;/p&gt;

&lt;p&gt;As an SDE, you are &lt;strong&gt;not&lt;/strong&gt; expected to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design Kubernetes clusters from scratch&lt;/li&gt;
&lt;li&gt;Be an expert in Terraform modules&lt;/li&gt;
&lt;li&gt;Tune networking or kernel internals&lt;/li&gt;
&lt;li&gt;Fully replace a DevOps/SRE team&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Minimum DevOps Knowledge Every SDE Should Have ✅
&lt;/h2&gt;

&lt;p&gt;This is the baseline I’ve seen across healthy engineering teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Deployment Awareness
&lt;/h3&gt;

&lt;p&gt;You should know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How your service gets deployed&lt;/li&gt;
&lt;li&gt;What happens after you merge to main&lt;/li&gt;
&lt;li&gt;Where to look when deployments fail&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t need to build pipelines — but you must understand them.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Logging &amp;amp; Monitoring
&lt;/h3&gt;

&lt;p&gt;If your code runs in production, you should know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where logs are stored&lt;/li&gt;
&lt;li&gt;How to search and filter them&lt;/li&gt;
&lt;li&gt;What “normal” vs “broken” looks like&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can’t debug your own service, someone else will — and they won’t be happy about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Basic Cloud &amp;amp; Container Concepts
&lt;/h3&gt;

&lt;p&gt;You don’t need deep expertise, but you should understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What containers are&lt;/li&gt;
&lt;li&gt;Why environment variables matter&lt;/li&gt;
&lt;li&gt;What scaling actually means&lt;/li&gt;
&lt;li&gt;Why stateless services are preferred&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is table-stakes knowledge now.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. CI/CD Basics
&lt;/h3&gt;

&lt;p&gt;You should be comfortable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading pipeline configs&lt;/li&gt;
&lt;li&gt;Understanding failed builds&lt;/li&gt;
&lt;li&gt;Knowing when a rollback is required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pipelines are part of the codebase. Ignoring them isn’t an option.&lt;/p&gt;




&lt;h2&gt;
  
  
  Kubernetes: How Deep Should You Go?
&lt;/h2&gt;

&lt;p&gt;You &lt;em&gt;don’t&lt;/em&gt; need to become a Kubernetes expert overnight.&lt;/p&gt;

&lt;p&gt;But as an SDE, it helps to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Pods, Services, and Deployments are&lt;/li&gt;
&lt;li&gt;How your app is exposed&lt;/li&gt;
&lt;li&gt;How config and secrets are injected&lt;/li&gt;
&lt;li&gt;How crashes and restarts work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want a structured, developer-friendly way to learn this, I’ve documented my own journey here:&lt;br&gt;
👉 &lt;strong&gt;30 Days of Kubernetes for Backend Developers&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://nileshblog.tech/category/backend-dev/kubernetes/30-days-kubernetes/" rel="noopener noreferrer"&gt;https://nileshblog.tech/category/backend-dev/kubernetes/30-days-kubernetes/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s written from a developer’s perspective — not an infra-first one — and focuses on &lt;em&gt;just enough Kubernetes&lt;/em&gt; to be effective.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Real Mistake I Made Early On
&lt;/h2&gt;

&lt;p&gt;Early in my career, I treated deployments as “not my responsibility.”&lt;/p&gt;

&lt;p&gt;My service deployed automatically, so I never checked the pipeline. One day, a config change caused the app to crash-loop in production.&lt;/p&gt;

&lt;p&gt;The logs clearly explained the issue.&lt;/p&gt;

&lt;p&gt;I just didn’t know where to find them.&lt;/p&gt;

&lt;p&gt;What I learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you write the code, you own how it behaves&lt;/li&gt;
&lt;li&gt;DevOps knowledge isn’t about control — it’s about responsibility&lt;/li&gt;
&lt;li&gt;Learning the basics is cheaper than debugging blindly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That mistake permanently changed how I approach production.&lt;/p&gt;




&lt;h2&gt;
  
  
  How DevOps Expectations Scale With Seniority
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Junior SDE
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Understand deployments conceptually&lt;/li&gt;
&lt;li&gt;Read logs and metrics&lt;/li&gt;
&lt;li&gt;Fix CI-related failures&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Mid-Level SDE
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Debug production issues independently&lt;/li&gt;
&lt;li&gt;Understand scaling and configuration&lt;/li&gt;
&lt;li&gt;Make small infra or pipeline changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Senior SDE
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Design services with operability in mind&lt;/li&gt;
&lt;li&gt;Review infra changes safely&lt;/li&gt;
&lt;li&gt;Mentor others on production readiness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice the pattern?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Depth increases — scope doesn’t.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You don’t become a DevOps engineer.&lt;br&gt;
You become a more production-aware engineer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Verdict
&lt;/h2&gt;

&lt;p&gt;So how much DevOps knowledge is required for an SDE?&lt;/p&gt;

&lt;p&gt;Enough to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Own your code in production&lt;/li&gt;
&lt;li&gt;Debug issues confidently&lt;/li&gt;
&lt;li&gt;Collaborate effectively with DevOps/SRE teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not enough to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace DevOps engineers&lt;/li&gt;
&lt;li&gt;Run infrastructure alone&lt;/li&gt;
&lt;li&gt;Burn out doing two jobs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DevOps knowledge isn’t about role overlap — it’s about shared responsibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you can ship code &lt;em&gt;and&lt;/em&gt; understand what happens after shipping, you’re exactly where you should be.&lt;/p&gt;




&lt;p&gt;💬 &lt;strong&gt;Discussion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;How much DevOps knowledge is expected in your current role?&lt;br&gt;
And where do you think the line &lt;em&gt;should&lt;/em&gt; be?&lt;/p&gt;

</description>
      <category>devops</category>
      <category>software</category>
      <category>sde</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
