<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>The Backend Engineer's Playbook on Lorbic</title><link>http://localhost:1313/series/the-backend-engineers-playbook/</link><description>Recent content in The Backend Engineer's Playbook on Lorbic</description><generator>Hugo</generator><language>en</language><lastBuildDate>Thu, 13 Aug 2026 18:00:00 +0530</lastBuildDate><atom:link href="http://localhost:1313/series/the-backend-engineers-playbook/index.xml" rel="self" type="application/rss+xml"/><item><title>How Go Channels Actually Work</title><link>http://localhost:1313/go-channels-deep-dive/</link><pubDate>Thu, 13 Aug 2026 18:00:00 +0530</pubDate><guid>http://localhost:1313/go-channels-deep-dive/</guid><description>&lt;p>A single unbuffered channel send without an active receiver is enough to silently lock up a production worker pool, leaking memory until your service gets killed by the OS kernel.&lt;/p>
&lt;p>On the surface, Go channels look simple: they synchronize concurrent execution without manual mutex management. But under heavy load, a minor oversight in channel sizing or worker coordination blocks the scheduler, leaks memory, or crashes processes with runtime panics.&lt;/p>
&lt;p>&lt;picture class="optimized-image-container">&lt;source srcset="http://localhost:1313/go-channels-deep-dive/go-scheduler-meme_hu_524f15f4ab89fd6f.webp 480w, http://localhost:1313/go-channels-deep-dive/go-scheduler-meme_hu_50f95d885458376d.webp 646w" sizes="(max-width: 800px) 100vw, 800px" type="image/webp">&lt;img src="http://localhost:1313/go-channels-deep-dive/go-scheduler-meme_hu_50f95d885458376d.webp" width="646" height="797" alt="The Go scheduler coordinating 10,000 goroutines on a single-core CPU" loading="eager" decoding="async" fetchpriority="high" class="img-fluid" />
 &lt;/picture>&lt;/p></description></item><item><title>Designing a Usage-Based Billing Pipeline for SaaS</title><link>http://localhost:1313/designing-a-usage-based-billing-pipeline-for-saas/</link><pubDate>Sat, 01 Aug 2026 17:26:52 +0530</pubDate><guid>http://localhost:1313/designing-a-usage-based-billing-pipeline-for-saas/</guid><description>&lt;p>In &lt;a href="http://localhost:1313/posts/2026-07-01-how-multi-tenant-saas-works/" data-preview-title="How Multi-Tenant SaaS Actually Works" data-preview-desc="A complete system design of Relay, a multi-tenant AI API gateway. Covers multi-tenant database architecture (silo vs pool vs bridge), API key authentication, provider routing with failover, dual-layer rate limiting, token-based billing, response caching, row-level security, tenant provisioning, and observability. Full Postgres schemas, mermaid diagrams, and Go snippets included." data-preview-time="37 min read">How Multi-Tenant SaaS Actually Works&lt;/a>, I left one major promise unfulfilled at the end: &lt;em>&amp;ldquo;Billing is an entire system design on its own. The billing pipeline gets its own post.&amp;rdquo;&lt;/em>&lt;/p></description></item><item><title>Couchbase Index Best Practices and Query Performance Tuning</title><link>http://localhost:1313/couchbase-index-best-practices-performance-tuning/</link><pubDate>Fri, 31 Jul 2026 23:00:00 +0530</pubDate><guid>http://localhost:1313/couchbase-index-best-practices-performance-tuning/</guid><description>&lt;p>Most Couchbase performance tickets I have seen end the same way: someone adds more nodes, the dashboard looks a little better for a week, and the same query shows up in the slow log a month later. The node count was never the problem. The index was.&lt;/p>
&lt;p>This is a working reference, not an essay. I already wrote &lt;a href="http://localhost:1313/what-couchbase-taught-me-about-system-thinking/">the reflective version&lt;/a> of what indexing in Couchbase teaches you about systems in general. This post skips the reflection and gets straight to the decisions: which index type to reach for, how to order composite keys, how to tell if a query is actually using what you built, and which four or five mistakes account for most of the slow queries you will ever debug. Couchbase&amp;rsquo;s own documentation is the primary source for the recommendations below. Every example runs against &lt;code>travel-sample&lt;/code>, the sample bucket Couchbase ships with every install, so you can paste these into your own cluster and see the plan yourself.&lt;/p></description></item><item><title>API Design for Backend Systems</title><link>http://localhost:1313/api-design-for-backend-systems/</link><pubDate>Sun, 26 Jul 2026 19:00:00 +0530</pubDate><guid>http://localhost:1313/api-design-for-backend-systems/</guid><description>&lt;p>A few weeks ago I designed &lt;a href="http://localhost:1313/how-multi-tenant-saas-works/">Relay&lt;/a>, a multi-tenant AI API gateway, as a system design exercise. That post covered the database, the auth, the billing. It did not cover the thing every one of those systems is sitting behind: the API itself.&lt;/p>
&lt;p>Here is the question that post left open. When someone builds &lt;code>GET /v1/requests&lt;/code> to list a tenant&amp;rsquo;s API call history, what should that endpoint actually look like? Offset or cursor pagination? What does the response envelope contain? What happens when Relay needs to add a filter that does not fit in a query string? What does a webhook payload look like when Relay tells a tenant &amp;ldquo;your batch job finished&amp;rdquo;? None of that is specific to AI gateways. It is the same decisions every backend API makes, made badly often enough that &amp;ldquo;REST API&amp;rdquo; has become a phrase that means &amp;ldquo;JSON over HTTP, structure unspecified.&amp;rdquo;&lt;/p></description></item><item><title>Cache-Driven Development: Saving Your Database From Itself</title><link>http://localhost:1313/cache-driven-development/</link><pubDate>Wed, 22 Jul 2026 12:00:00 +0530</pubDate><guid>http://localhost:1313/cache-driven-development/</guid><description>&lt;p>There is a moment in every backend engineer&amp;rsquo;s life when their database starts refusing connections.&lt;/p>
&lt;p>Picture 2 a.m. on a Tuesday. The app is operating under normal traffic, nothing unusual. But the database connection pool is saturated. Queries are timing out. The monitoring dashboard shows 50,000 database operations per second, far beyond what the system should be handling.&lt;/p>
&lt;p>When someone pulls the slow-query logs, the pattern is immediately clear. The same query appears thousands of times:&lt;/p></description></item><item><title>How Multi-Tenant SaaS Actually Works</title><link>http://localhost:1313/how-multi-tenant-saas-works/</link><pubDate>Wed, 01 Jul 2026 00:00:00 +0530</pubDate><guid>http://localhost:1313/how-multi-tenant-saas-works/</guid><description>&lt;p>For the past month I have been reading about multi-tenant SaaS architecture. Not as an academic exercise. I kept running into the same questions on every project I looked at: where exactly does tenant data go, how do you stop one customer&amp;rsquo;s bug from becoming every customer&amp;rsquo;s problem, how does billing actually work at the database level. The blog posts I found were either too abstract or skipped the hard parts entirely.&lt;/p></description></item><item><title>So, We Are Writing Efficient Software Again</title><link>http://localhost:1313/so-we-are-writing-efficient-software-again/</link><pubDate>Wed, 17 Jun 2026 20:00:00 +0530</pubDate><guid>http://localhost:1313/so-we-are-writing-efficient-software-again/</guid><description>&lt;p>I wanted to upgrade the RAM in my PC.&lt;/p>
&lt;p>Nothing fancy. I bought 32GB in 2024 and I wanted to double it. I opened a tab, checked the price, and closed the tab. Then I sat quietly for a moment.&lt;/p>
&lt;p>The same 32GB kit I bought in 2024 now costs more than double. DDR5 prices have gone up roughly 400% since mid-2025 [1]. DDR4 is not much better. A kit that cost $60–$90 in late 2025 now sells for $150–$180 [2].&lt;/p></description></item><item><title>A Love Letter to the L1 Cache</title><link>http://localhost:1313/love-letter-to-the-l1-cache/</link><pubDate>Mon, 15 Jun 2026 19:00:00 +0530</pubDate><guid>http://localhost:1313/love-letter-to-the-l1-cache/</guid><description>&lt;p>I recently spent four hours staring at a benchmark that didn&amp;rsquo;t make sense.&lt;/p>
&lt;p>It started while working on &lt;a href="https://github.com/vikash-paf/derelict-facility" target="_blank" rel="noopener noreferrer">Derelict Facility&lt;/a>, my grid-based game engine in Go. I was trying to tighten the main update loop, specifically the part that iterates over every entity on the map each frame. I pulled out a small benchmark to isolate the cost, and something looked wrong.&lt;/p>
&lt;p>I had two Go structs. They held the exact same data: two booleans and a 64-bit integer. I was iterating over a slice of 10 million of these structs, doing a simple addition. They should have been identical in performance.&lt;/p></description></item><item><title>Why Explaining Technical Difficulty is Hard</title><link>http://localhost:1313/why-explaining-technical-difficulty-is-hard/</link><pubDate>Thu, 14 May 2026 01:00:00 +0530</pubDate><guid>http://localhost:1313/why-explaining-technical-difficulty-is-hard/</guid><description>&lt;p>&amp;ldquo;Can we just add a real-time visitor counter to the homepage? It&amp;rsquo;s just a query, right&amp;rdquo;?&lt;/p>
&lt;p>Every engineer has heard some variation of this. On the surface, the logic is sound. You have data, you have a UI, and you want to connect them. In the world of business requirements, this is a solved problem. You write a line of code, and the feature exists.&lt;/p>
&lt;p>But your database doesn&amp;rsquo;t care about business logic. It cares about &lt;strong>Infrastructure Constraints&lt;/strong>.&lt;/p></description></item><item><title>Just About Go Time</title><link>http://localhost:1313/just-about-go-time/</link><pubDate>Sun, 10 May 2026 22:00:00 +0530</pubDate><guid>http://localhost:1313/just-about-go-time/</guid><description>&lt;p>Time is an illusion. Or more accurately, time is a political consensus poorly masquerading as physics.&lt;/p>
&lt;p>&lt;picture class="optimized-image-container">&lt;source srcset="http://localhost:1313/just-about-go-time/time-theory-meme_hu_c027f9156a69cf21.webp 480w, http://localhost:1313/just-about-go-time/time-theory-meme_hu_c74845a5e28401ee.webp 800w, http://localhost:1313/just-about-go-time/time-theory-meme_hu_22fbca4a5f8175a5.webp 1200w, http://localhost:1313/just-about-go-time/time-theory-meme_hu_c495ad8b67b2bacf.webp 1222w" sizes="(max-width: 800px) 100vw, 800px" type="image/webp">&lt;img src="http://localhost:1313/just-about-go-time/time-theory-meme_hu_c495ad8b67b2bacf.webp" width="1222" height="1514" alt="Time is relative, absolute, and a scam" loading="eager" decoding="async" fetchpriority="high" class="img-fluid" />
 &lt;/picture>&lt;/p>
&lt;p>If you&amp;rsquo;ve ever seen Dylan Beattie&amp;rsquo;s &amp;ldquo;Plain Text&amp;rdquo; &lt;a href="https://www.youtube.com/watch?v=gd5uJ7Nlvvo" target="_blank" rel="noopener noreferrer">talk&lt;/a>, you know that humans have spent centuries making data storage as complicated as possible. But text encoding has nothing on time zones.&lt;/p>
&lt;p>As engineers, we like to pretend that &lt;code>time.Now()&lt;/code> returns an objective truth. It doesn&amp;rsquo;t. It returns a snapshot of a highly contested, historically unstable set of political boundaries. In 2011, the island nation of Samoa decided they wanted to align their workweek with Australia rather than the United States. To do this, they didn&amp;rsquo;t just change their clocks; they completely skipped Friday, December 30th. At 11:59 PM on Thursday, the clock ticked over, and it was suddenly Saturday.&lt;/p></description></item><item><title>Understanding CPU Caches in Go</title><link>http://localhost:1313/cpu-caches-in-go/</link><pubDate>Tue, 31 Mar 2026 22:15:00 +0530</pubDate><guid>http://localhost:1313/cpu-caches-in-go/</guid><description>&lt;p>When you&amp;rsquo;re building Go services that handle millions of operations per second, the hardware beneath your abstractions starts to matter. Specifically, the CPU cache hierarchy, and whether your data fits in it.&lt;/p>
&lt;hr>
&lt;h4 id="the-hardware-context-its-not-just-ram">The Hardware Context: It&amp;rsquo;s Not Just &amp;ldquo;RAM&amp;rdquo;&lt;a class="anchorjs-link" href="#the-hardware-context-its-not-just-ram" aria-label="Link to section: The Hardware Context: It&amp;rsquo;s Not Just &amp;ldquo;RAM&amp;rdquo;">&lt;/a>&lt;/h4>&lt;p>Your server has 32GB or 64GB of RAM, but the CPU avoids touching it whenever possible. Instead, it works through a chain of caches:&lt;/p></description></item><item><title>AI Coding in 2026: Productivity Multipliers vs. Skill Replacements</title><link>http://localhost:1313/ai-coding-productivity-vs-skill/</link><pubDate>Sat, 28 Mar 2026 23:00:00 +0530</pubDate><guid>http://localhost:1313/ai-coding-productivity-vs-skill/</guid><description>&lt;p>&amp;ldquo;Write a REST API with authentication&amp;rdquo;.&lt;/p>
&lt;p>I hit enter. Thirty seconds later, Claude spat out 400 lines of perfectly formatted Go code. JWT middleware, password hashing, error handling, even rate limiting. It looked professional. It looked production-ready.&lt;/p>
&lt;p>It took me three hours to figure out why the token refresh logic had a race condition.&lt;/p>
&lt;p>This is AI-assisted coding in 2026. It&amp;rsquo;s not magic. It&amp;rsquo;s not a replacement. It&amp;rsquo;s a very fast junior developer that never gets tired, never complains, and confidently makes mistakes you won&amp;rsquo;t catch unless you actually understand the &lt;strong>architectural nuances&lt;/strong> of what you&amp;rsquo;re building.&lt;/p></description></item><item><title>Fast Docker CI: Stop Rebuilding Container Images on Every Commit</title><link>http://localhost:1313/stop-rebuilding-docker-images-runtime-containers/</link><pubDate>Sun, 15 Feb 2026 02:30:00 +0530</pubDate><guid>http://localhost:1313/stop-rebuilding-docker-images-runtime-containers/</guid><description>&lt;p>I used to rebuild my Docker image every time I fixed a typo. A one-line change meant waiting 2-3 minutes for Docker to rebuild layers, reinstall dependencies, and restart the container. I thought this was just the cost of containerized development.&lt;/p>
&lt;p>Then I discovered runtime containers. Same isolated environment, same reproducibility, but code changes reflect instantly. No rebuilds. No waiting. The runtime lives in the container, the code lives on the host.&lt;/p></description></item><item><title>Python Background Workers: Architecture, Queues, and Retry Strategies</title><link>http://localhost:1313/building-production-ready-background-workers-in-python/</link><pubDate>Sun, 01 Feb 2026 13:00:00 +0530</pubDate><guid>http://localhost:1313/building-production-ready-background-workers-in-python/</guid><description>&lt;p>I thought processing audio in the background was simple: spawn a thread, run the script, save the file. Then I hit 200 concurrent requests, and it failed epically.&lt;/p>
&lt;p>The CPU spiked to full usage because of pydub&amp;rsquo;s processing. The TTS API didn&amp;rsquo;t rate-limit me but, it was horribly slow. Then the jobs started failing. Half the jobs died silently. The other half wrote corrupted files because of race conditions I didn&amp;rsquo;t know existed. And when I deployed a little fix? The deployment killed in-flight jobs, leaving orphaned audio segments scattered across cloud storage directory.&lt;/p></description></item><item><title>Go Struct Field Alignment: How Memory Padding Wastes Your RAM</title><link>http://localhost:1313/go-struct-field-alignment/</link><pubDate>Sat, 24 Jan 2026 10:00:00 +0530</pubDate><guid>http://localhost:1313/go-struct-field-alignment/</guid><description>&lt;p>You write a struct to represent a database entity. Maybe 10 fields, maybe 20. What could possibly go wrong?&lt;/p>
&lt;p>Nothing, according to your tests. But somewhere in production, your heap is 30% larger than it should be, your Garbage Collector is working overtime, and your L1 cache is not used properly. The reason? &lt;strong>Invisible padding bytes&lt;/strong> silently inflating every instance of your struct.&lt;/p>
&lt;p>This is the story of struct field alignment: a memory optimization that costs nothing to implement but can significantly improve performance.&lt;/p></description></item><item><title>Memory Mechanics In Go - Stack vs Heap</title><link>http://localhost:1313/memory-mechanics-stack-vs-heap-in-go/</link><pubDate>Mon, 12 Jan 2026 00:10:00 +0530</pubDate><guid>http://localhost:1313/memory-mechanics-stack-vs-heap-in-go/</guid><description>&lt;p>We often talk about &amp;ldquo;fast&amp;rdquo; code in terms of Big O notation or algorithmic complexity. But in systems programming languages like Go, &amp;ldquo;fast&amp;rdquo; is often a function of &lt;em>where&lt;/em> your data lives in memory.&lt;/p>
&lt;p>When optimizing for high throughput, efficient loops and database indexes are only part of the story. Eventually, you have to talk about the Stack and the Heap.&lt;/p>
&lt;p>Understanding the difference isn&amp;rsquo;t just trivia. It is the difference between a service that hums along at 100k OPS with flat latency, and one that chokes on Garbage Collection (GC) pauses every few seconds.&lt;/p></description></item><item><title>OLTP vs OLAP - Why You Need Two Databases</title><link>http://localhost:1313/oltp-vs-olap-why-you-need-two-databases/</link><pubDate>Sun, 11 Jan 2026 21:00:00 +0530</pubDate><guid>http://localhost:1313/oltp-vs-olap-why-you-need-two-databases/</guid><description>&lt;p>At a recent ClickHouse conference in New Delhi, I attended this Saturday. There were many interesting sessions, but one that stood out was a talk on multi-tenant analytics at scale. I was reminded of a fundamental truth in backend engineering: &amp;ldquo;The database that runs your app cannot be the database that analyzes your app&amp;rdquo;.&lt;/p>
&lt;p>Early in a startup&amp;rsquo;s life, we shove everything into one database. User profiles, session data, logs, and analytics events all live in the same Postgres, Mongo, or Couchbase instance. It works, until it throttles.&lt;/p></description></item><item><title>Go Garbage Collector Mechanics: Pacer, GOGC, and Allocation Latency</title><link>http://localhost:1313/dont-take-out-the-garbage-go-gc-deep-dive/</link><pubDate>Wed, 07 Jan 2026 00:21:12 +0530</pubDate><guid>http://localhost:1313/dont-take-out-the-garbage-go-gc-deep-dive/</guid><description>&lt;p>In the world of high-throughput backend services, we often obsess over the usual suspects of performance: database indexing, network latency, and algorithmic complexity. But recently, while debugging our core gateway service (&lt;code>backend-gw&lt;/code>), I encountered a bottleneck that defied standard logic.&lt;/p>
&lt;p>The service was &lt;strong>CPU-bound&lt;/strong>, yet active heap usage was surprisingly low (~200MB). P99 latency was spiking at random intervals, but database queries were returning in milliseconds.&lt;/p>
&lt;p>The culprit was not the business logic. It was &lt;strong>memory management&lt;/strong>. I was effectively running a Denial-of-Service attack on my own runtime.&lt;/p></description></item><item><title>What Couchbase Taught Me About System Thinking</title><link>http://localhost:1313/what-couchbase-taught-me-about-system-thinking/</link><pubDate>Tue, 18 Nov 2025 02:20:06 +0530</pubDate><guid>http://localhost:1313/what-couchbase-taught-me-about-system-thinking/</guid><description>&lt;h2 id="couchbase-internals-indexes-queries-consistency-and-performance">Couchbase Internals: Indexes, Queries, Consistency, and Performance&lt;a class="anchorjs-link" href="#couchbase-internals-indexes-queries-consistency-and-performance" aria-label="Link to section: Couchbase Internals: Indexes, Queries, Consistency, and Performance">&lt;/a>&lt;/h2>&lt;h3 id="introduction">Introduction&lt;a class="anchorjs-link" href="#introduction" aria-label="Link to section: Introduction">&lt;/a>&lt;/h3>&lt;p>Over the last few years I&amp;rsquo;ve lived deep inside backend systems, and for the past year and a half Couchbase has been my daily companion. Working with Go services that depend on Couchbase taught me that the real lessons aren&amp;rsquo;t in the marketing slides or quick‑start guides. They&amp;rsquo;re in the internals: how indexes are built, how queries are planned, how consistency flags change the story, and how durability levels quietly decide whether your system survives a failure or not.&lt;/p></description></item></channel></rss>