Back to home

Blog

Thoughts on backend engineering, architecture, and web development.

Race Conditions in Node.js: They Exist and They'll Bite You

Node.js is single-threaded, but race conditions are real. Here's how they happen in async code and how to prevent them.

3 min read

Bun vs Node.js: A Practical Comparison for Backend Engineers

Bun promises speed. But is it ready for production backend work? A real-world comparison across the things that actually matter.

3 min read

The N+1 Query Problem: Why Your API is Slow

The N+1 problem is the most common performance killer in backend applications. Here's how to detect and fix it across different ORMs.

3 min read

Designing Idempotent APIs: Why Your Payment Endpoint Charges Twice

Your user clicked 'Pay' twice and got charged twice. Here's how to design APIs that handle retries, network failures, and duplicate requests without duplicating side effects.

6 min read

The Node.js Event Loop: Beyond the Basics

Most explanations of the event loop are oversimplified. Here's what actually happens, phase by phase, and why it matters.

3 min read

Docker Multi-Stage Builds: From 1.2GB to 80MB

A real walkthrough of shrinking a Node.js Docker image from 1.2GB to 80MB using multi-stage builds, layer caching, distroless bases, and a production-ready Dockerfile template.

5 min read

Database Indexing: What Every Backend Engineer Should Know

Indexes can make or break your application performance. Here's how they work internally and when to use them.

3 min read

Big O Notation: The Practical Guide for Working Engineers

Forget the academic proofs. Here's how to spot O(n^2) hiding in your code, why hash maps change everything, and real refactoring examples that turned minutes into milliseconds.

6 min read

Database Connection Pooling: Why Your Server Crashes at 100 Concurrent Users

You're opening a new database connection for every request and wondering why your server dies under load. Here's how connection pooling works and how to configure it properly.

6 min read

API Rate Limiting Done Right: Algorithms and Implementation

Rate limiting protects your API from abuse. Here's how the major algorithms work and which one to pick for your use case.

3 min read

TypeScript Strict Mode: Stop Using `any` and Start Shipping Safer Code

Every `any` in your codebase is a bug waiting to happen. Here's how to enable strict mode, survive the migration, and use TypeScript the way it was meant to be used.

5 min read

Git Rebase vs Merge: When to Use Which

A practical guide to rebase vs merge from someone who's destroyed production history and lived to tell about it. Interactive rebase, fixup, squash, and real team workflows.

6 min read

Git Bisect: Find the Bug in 10 Steps, Not 10 Hours

Binary search through your commit history to find exactly which commit broke things. Manual, automated, and CI-integrated approaches.

6 min read

Redis Beyond Caching: Queues, Pub/Sub, and Rate Limiters

Redis is not just a cache. I've used it as a message queue, a rate limiter, a leaderboard engine, and a real-time event bus. Here's how, and when to stop.

6 min read

Graceful Shutdown in Node.js: Stop Killing Your Users' Requests

Your Node.js server gets SIGTERM, immediately dies, and 47 users get 502 errors. Here's how to shut down properly in production.

6 min read

MongoDB Aggregation Pipeline: Replace Your Application Logic with Database Logic

Stop fetching all documents and filtering in JavaScript. MongoDB's aggregation pipeline can do joins, grouping, pagination, and analytics in a single query.

6 min read

Hash Tables Under the Hood: Why Object Lookup is O(1)

Hash tables power objects, dictionaries, sets, and caches. Here's what actually happens when you write obj[key], and when O(1) breaks down.

7 min read

Error Handling Patterns in Node.js: Stop Swallowing Errors

Empty catch blocks, generic error messages, and silent failures. Here are the patterns I use to handle errors properly in production Node.js applications.

6 min read