<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Insights on Manas Yadav</title><link>https://manas2297.github.io/posts/</link><description>Recent content in Insights on Manas Yadav</description><generator>Hugo</generator><language>en</language><atom:link href="https://manas2297.github.io/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Graceful Shutdown in Kubernetes for Go and Node.js Services</title><link>https://manas2297.github.io/posts/graceful-shutdown-kubernetes-go-nodejs/</link><pubDate>Thu, 08 Oct 2026 00:00:00 +0000</pubDate><guid>https://manas2297.github.io/posts/graceful-shutdown-kubernetes-go-nodejs/</guid><description>&lt;p>Does your error rate tick up a little on every deploy? That&amp;rsquo;s probably not a bug in the new version. It&amp;rsquo;s a shutdown problem. A handful of &lt;code>502&lt;/code>s and connection resets per rollout is so common that lots of teams treat it as normal. It isn&amp;rsquo;t, and the fix is mostly plumbing.&lt;/p>
&lt;h2 id="what-actually-happens-when-a-pod-is-terminated">What actually happens when a pod is terminated&lt;/h2>
&lt;p>When Kubernetes stops a pod (a rollout, a scale-down, a node drain), two things start &lt;em>at the same time&lt;/em>:&lt;/p></description></item><item><title>Backpressure and Load Shedding: Keeping Services Alive Under Overload</title><link>https://manas2297.github.io/posts/backpressure-load-shedding-services/</link><pubDate>Tue, 06 Oct 2026 00:00:00 +0000</pubDate><guid>https://manas2297.github.io/posts/backpressure-load-shedding-services/</guid><description>&lt;p>Services rarely die from a bit more traffic than they can handle. They die because they &lt;em>accept&lt;/em> that traffic, queue it up, and then serve every request slowly instead of serving most of them quickly. Latency climbs. Clients time out and retry, the queue grows faster, and before long the service is busy working on requests nobody is waiting for anymore.&lt;/p>
&lt;p>The fix feels backwards: to stay up under overload, a service has to say no to some work, early and cheaply.&lt;/p></description></item><item><title>Timeouts, Retries, and Backoff: How to Call Other Services Without Causing an Outage</title><link>https://manas2297.github.io/posts/timeouts-retries-backoff/</link><pubDate>Sun, 04 Oct 2026 00:00:00 +0000</pubDate><guid>https://manas2297.github.io/posts/timeouts-retries-backoff/</guid><description>&lt;p>A network call can fail fast, fail slowly, or never come back. Failing fast is the easy case. The other two cause outages. A missing timeout ties up resources until the process runs out, and a naive retry takes a struggling dependency and hits it three times harder while it&amp;rsquo;s down.&lt;/p>
&lt;p>Timeout and retry logic gets copy-pasted around every backend I&amp;rsquo;ve seen, and it&amp;rsquo;s dangerous to get wrong. Here&amp;rsquo;s how I think about it.&lt;/p></description></item><item><title>The Transactional Outbox Pattern and Idempotent Consumers, Explained</title><link>https://manas2297.github.io/posts/transactional-outbox-idempotent-consumers/</link><pubDate>Thu, 01 Oct 2026 00:00:00 +0000</pubDate><guid>https://manas2297.github.io/posts/transactional-outbox-idempotent-consumers/</guid><description>&lt;p>This looks completely reasonable. It&amp;rsquo;s quietly broken:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">func&lt;/span> &lt;span style="color:#6639ba">PlaceOrder&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">ctx&lt;/span> &lt;span style="color:#1f2328">context&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#1f2328">Context&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">o&lt;/span> &lt;span style="color:#1f2328">Order&lt;/span>&lt;span style="color:#1f2328">)&lt;/span> &lt;span style="color:#cf222e">error&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#cf222e">if&lt;/span> &lt;span style="color:#1f2328">err&lt;/span> &lt;span style="color:#0550ae">:=&lt;/span> &lt;span style="color:#1f2328">db&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">InsertOrder&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">ctx&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">o&lt;/span>&lt;span style="color:#1f2328">);&lt;/span> &lt;span style="color:#1f2328">err&lt;/span> &lt;span style="color:#0550ae">!=&lt;/span> &lt;span style="color:#cf222e">nil&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#cf222e">return&lt;/span> &lt;span style="color:#1f2328">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#1f2328">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#cf222e">return&lt;/span> &lt;span style="color:#1f2328">producer&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">Publish&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">ctx&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#0a3069">&amp;#34;orders.placed&amp;#34;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">o&lt;/span>&lt;span style="color:#1f2328">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#1f2328">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If the process crashes, the network blips, or Kafka is briefly unavailable between those two lines, the order exists but the event never goes out. The warehouse never ships it. The email never sends. Swap the calls around and you get the opposite: an event for an order that was never saved.&lt;/p>
&lt;p>That&amp;rsquo;s the dual-write problem. You want to update two systems atomically and no transaction spans both. Retries don&amp;rsquo;t help, because you can&amp;rsquo;t tell whether the first attempt partly succeeded.&lt;/p></description></item><item><title>Reading PostgreSQL EXPLAIN ANALYZE: A Backend Engineer's Guide to Slow Queries</title><link>https://manas2297.github.io/posts/postgres-explain-analyze-guide/</link><pubDate>Mon, 28 Sep 2026 00:00:00 +0000</pubDate><guid>https://manas2297.github.io/posts/postgres-explain-analyze-guide/</guid><description>&lt;p>Most slow API endpoints I&amp;rsquo;ve looked at weren&amp;rsquo;t slow because of application code. They were slow because of one query, and that query was slow because Postgres picked a plan nobody expected. &lt;code>EXPLAIN ANALYZE&lt;/code> shows you that plan. Reading it well is one of the most useful skills a backend engineer can pick up.&lt;/p>
&lt;h2 id="always-use-analyze-and-buffers">Always use ANALYZE and BUFFERS&lt;/h2>
&lt;p>Plain &lt;code>EXPLAIN&lt;/code> shows what Postgres &lt;em>plans&lt;/em> to do. &lt;code>EXPLAIN ANALYZE&lt;/code> runs the query and shows what actually happened. Add &lt;code>BUFFERS&lt;/code> to see how much data it touched:&lt;/p></description></item><item><title>Kafka at Scale: Partitions, Consumer Lag, Rebalancing, and Running It in Production</title><link>https://manas2297.github.io/posts/kafka-at-scale-partitions-consumers-rebalancing/</link><pubDate>Wed, 23 Sep 2026 00:00:00 +0000</pubDate><guid>https://manas2297.github.io/posts/kafka-at-scale-partitions-consumers-rebalancing/</guid><description>&lt;p>Kafka will take almost anything you throw at it on day one. The trouble comes later. A topic can&amp;rsquo;t keep up because it has too few partitions. Consumers stop for 30 seconds every time a pod restarts. One broker runs hot while the rest idle. Nothing exotic, just the defaults meeting real traffic.&lt;/p>
&lt;p>These are the decisions I think matter most once Kafka is load-bearing. For the &amp;ldquo;why&amp;rdquo; behind the storage and replication model, read &lt;a href="https://manas2297.github.io/posts/kafka-internals-log-replication-isr/">Kafka internals&lt;/a> first.&lt;/p></description></item><item><title>Kafka Internals: Logs, Segments, Replication, and the ISR Explained</title><link>https://manas2297.github.io/posts/kafka-internals-log-replication-isr/</link><pubDate>Wed, 16 Sep 2026 00:00:00 +0000</pubDate><guid>https://manas2297.github.io/posts/kafka-internals-log-replication-isr/</guid><description>&lt;p>Kafka is easy to use and hard to operate well. Nearly all of the gap is internals. Once you know how a partition sits on disk and how replicas agree on what&amp;rsquo;s committed, most of the config options stop looking like magic. They turn into fairly obvious trade-offs.&lt;/p>
&lt;p>I&amp;rsquo;ll go bottom up: one partition on one disk, then replication, then producers and consumers. The operational side lives in the companion post on &lt;a href="https://manas2297.github.io/posts/kafka-at-scale-partitions-consumers-rebalancing/">running Kafka at scale&lt;/a>.&lt;/p></description></item><item><title>Go Performance Debugging: A Practical Guide to pprof, Traces, and the GC</title><link>https://manas2297.github.io/posts/go-performance-debugging-pprof/</link><pubDate>Wed, 09 Sep 2026 00:00:00 +0000</pubDate><guid>https://manas2297.github.io/posts/go-performance-debugging-pprof/</guid><description>&lt;p>Go makes it easy to write fast code. It also makes it easy to write code that&amp;rsquo;s slow for reasons you&amp;rsquo;ll never spot by reading it. The tooling to find out &lt;em>why&lt;/em> ships with the language and is safe to run in production. Most teams barely touch it.&lt;/p>
&lt;p>Here&amp;rsquo;s the workflow I follow when a Go service is slower than it should be, roughly in the order the steps tend to pay off.&lt;/p></description></item><item><title>Event Loop Lag in Node.js: Using It to Debug Performance and CPU Throttling</title><link>https://manas2297.github.io/posts/nodejs-event-loop-lag-cpu-throttling/</link><pubDate>Wed, 02 Sep 2026 00:00:00 +0000</pubDate><guid>https://manas2297.github.io/posts/nodejs-event-loop-lag-cpu-throttling/</guid><description>&lt;p>A slow Node.js service sends most people straight to request latency and downstream calls. Reasonable, but it misses the most common Node-specific failure, which is the event loop itself falling behind. When that happens &lt;em>every&lt;/em> request in the process slows down at once, including the ones that do nothing expensive.&lt;/p>
&lt;p>Event loop lag catches it. It&amp;rsquo;s cheap to collect and easy to read once you know the patterns. It&amp;rsquo;s also the best tool I know for spotting something dashboards usually hide: CPU throttling in containers.&lt;/p></description></item><item><title>Node.js Event Loop Internals: What Actually Runs When</title><link>https://manas2297.github.io/posts/nodejs-event-loop-internals/</link><pubDate>Wed, 26 Aug 2026 00:00:00 +0000</pubDate><guid>https://manas2297.github.io/posts/nodejs-event-loop-internals/</guid><description>&lt;p>&amp;ldquo;Node is single-threaded&amp;rdquo; is one of those statements that&amp;rsquo;s true enough to repeat and wrong enough to cause outages. Your JavaScript runs on one thread. Node itself doesn&amp;rsquo;t. Knowing where that line sits is the difference between a service that handles 10k concurrent connections calmly and one that falls over the first time someone uploads a big JSON file.&lt;/p>
&lt;p>So here&amp;rsquo;s what the loop actually does, in order, followed by the mistakes that block it.&lt;/p></description></item><item><title>Distributed Locking Patterns in High-Concurrency Microservices</title><link>https://manas2297.github.io/posts/distributed-locking-patterns/</link><pubDate>Tue, 18 Aug 2026 00:00:00 +0000</pubDate><guid>https://manas2297.github.io/posts/distributed-locking-patterns/</guid><description>&lt;p>A &lt;code>sync.Mutex&lt;/code> protects memory inside one process. The moment you run three replicas of a service on Kubernetes, each pod has its own mutex, and they know nothing about each other. If two pods pick up work for the same customer at the same time, the mutex does nothing to stop them.&lt;/p>
&lt;p>That&amp;rsquo;s when people reach for a distributed lock. Fair enough, they&amp;rsquo;re useful. They&amp;rsquo;re also one of the easiest things in backend engineering to get subtly wrong, and quite often they&amp;rsquo;re not the right tool in the first place.&lt;/p></description></item><item><title>Building High-Throughput Kafka Event Pipelines in Go</title><link>https://manas2297.github.io/posts/go-kafka-event-streams/</link><pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate><guid>https://manas2297.github.io/posts/go-kafka-event-streams/</guid><description>&lt;p>Most Go Kafka services start out as a consumer loop, a channel, and a handful of goroutines reading from it. Fine at a few hundred messages a second. At tens of thousands, ordering breaks, memory climbs, and latency gets spiky in ways dashboards don&amp;rsquo;t explain.&lt;/p>
&lt;p>Below is the shape I reach for when a pipeline has to be fast &lt;em>and&lt;/em> correct.&lt;/p>
&lt;h2 id="the-naive-version-and-what-goes-wrong">The naive version and what goes wrong&lt;/h2>
&lt;p>Here&amp;rsquo;s the pattern almost everyone writes first:&lt;/p></description></item></channel></rss>