Designing Ad Click Aggregation: Exactly-Once Counting at Scale
Billions of clicks, billed to the cent: streaming aggregation with watermarks, dedupe, idempotent sinks, and lambda-style reconciliation.
Theme
Deep dives into designing scalable, reliable systems — URL shorteners, chat apps, rate limiters, caching, and more.
55 articles
Billions of clicks, billed to the cent: streaming aggregation with watermarks, dedupe, idempotent sinks, and lambda-style reconciliation.
How a CDN actually works: edge PoPs, origin shields, consistent-hash cache keys, purge fan-out, and the anycast vs DNS routing decision.
Build the cache, not just use it: slot-based sharding, gossip and failover, eviction under memory pressure, and the hot-key problem that shards can't solve.
Content-addressed chunks, delta sync, metadata vs block servers, and why 'last writer wins' is the wrong answer for file conflicts.
How do 50 people type into the same document without corrupting it? Operational transformation, CRDTs, and the server architecture that makes co-editing work.
Not how to use Kafka — how to build it: partitioned append-only logs, in-sync replica sets, high-watermarks, zero-copy reads, and log compaction.
Millions of users broadcasting location every 30 seconds, each visible only to friends: pub/sub fan-out, ephemeral state with TTLs, and the privacy-first data model.
Run a million strangers' untrusted programs a day without letting one of them own your fleet: sandbox layers, judge workers, resource limits, and contest-spike architecture.
Eleven nines of durability, exabyte scale: separating the metadata plane from immutable data blobs, erasure coding vs replication, and repair as a first-class workload.
Order books, price-time priority, single-threaded matching, and deterministic replay — how exchanges match millions of orders with microsecond latency.
Taylor Swift goes on sale and 500K people want the same 500 seats. Seat holds with TTLs, contention control, virtual queues, and never selling seat 14B twice.
A million drivers moving every 4 seconds, matched to riders in under 10: geosharded in-memory indexes, dispatch as a distributed transaction, and surge as a control loop.
Tracing every request would need a system bigger than the one being traced. Head vs tail sampling, span ingestion pipelines, and storage laid out for trace reads.
The always-writable database: sloppy quorums, R+W tuning, vector clocks vs LWW, read repair, anti-entropy with Merkle trees — the machinery behind Cassandra and Riak.
Dijkstra on a planet-sized graph would take seconds per query. Precomputed hierarchies answer it in milliseconds — plus map tiles and the live-traffic ETA loop.
How Google Spanner gives serializable transactions across continents: TrueTime's bounded clock uncertainty, commit-wait, Paxos groups, and 2PC on top.
Sync vs async replication, why failover loses writes, and how quorum systems skip the leader entirely. The trade-offs that set your durability story.
Hash vs range partitioning, choosing a shard key you won't regret, the hot-partition problem, and why cross-shard queries are the real cost of sharding.
Delayed jobs, cron at scale, and work claiming with SKIP LOCKED. Why every scheduler promises at-least-once and what that forces on your handlers.
Precompute every follower's timeline or assemble it per request? The celebrity edge case that breaks the pretty answer, and the hybrid everyone ships.
Why 'UPDATE balance' is a bug, how double-entry bookkeeping becomes a schema, and the idempotency and reconciliation machinery that keeps money honest.
Why auto-increment dies when you shard, why random UUIDs wreck index locality, and how time-ordered IDs like Snowflake and UUIDv7 thread the needle.
A lock with a TTL can expire while its holder still thinks it owns it. Fencing tokens fix what timeouts break — and most lock problems have better answers.
B-trees can't answer 2D questions. Geohash, quadtrees, and hex grids turn 'within 2km' into a prefix scan — plus the boundary problem that trips everyone.
Overloaded systems don't slow down gracefully — goodput collapses. Admission control, criticality tiers, and retry budgets decide what breaks and what survives.
Leader election, log replication, and the quorum-overlap trick that makes Raft safe. What etcd, Consul, and Kafka KRaft are actually doing under the hood.
Why column-oriented databases run analytical queries 100x faster than row-oriented ones — covering physical layout, compression algorithms, vectorized execution, and predicate pushdown with concrete examples.
A deep dive into how Kafka distributes work across consumers, why rebalancing stalls your pipeline, and how to choose an offset commit strategy that matches your delivery guarantee requirements.
Why PostgreSQL's connection model breaks under load, how PgBouncer fixes it, and how to configure transaction-mode pooling without getting bitten by prepared statements or advisory locks.
Why dual writes lose events, how the transactional outbox pattern fixes it, and the relay, ordering, and cleanup decisions that make it production-ready.
Signing, retries, ordering, and dead-lettering: the design decisions that separate reliable webhook delivery from silent event loss.
A fast producer and a slow consumer is a recipe for an out-of-memory crash. Backpressure is the discipline of letting the slow part tell the fast part to wait. Here is how to design it in.
More connections is not more throughput. Past a point, adding connections makes your database slower. Here is how pools actually work and how to size one without guessing.
How does a database survive a power cut mid-write without corrupting your data? The answer is a deceptively simple rule: log the change before you apply it. Here is why WAL is everywhere.
A Bloom filter answers 'have I seen this?' using a tiny fraction of the memory a real set would need. The price is false positives — and understanding that trade is the whole skill.
A single ACID transaction can't span order, payment, and inventory services. Sagas chain local transactions with compensating actions to keep distributed state consistent — eventually.
When a downstream service slows down, naive retries turn one sick dependency into a system-wide outage. A circuit breaker fails fast, sheds load, and gives the dependency room to recover.
You wrote to the database and then published an event — and the publish failed. Now your systems disagree. The outbox pattern makes the write and the event atomic without a two-phase commit.
When you add a node to a sharded cache, naive hashing remaps almost every key. Consistent hashing moves only a fraction. Here is the mechanism, the virtual-node fix, and the traps.
A practical guide to the design decisions that determine whether an event-driven system stays maintainable or quietly rots — delivery guarantees, ordering, idempotency, schema evolution, and the outbox.
Walk through the architecture of a production search system — inverted indexes, BM25 ranking, vector embeddings, and hybrid retrieval for 50M documents at 10K QPS.
A system design deep dive into building a notification platform that handles push, email, SMS, and in-app notifications at scale — covering architecture, priority queues, fan-out strategies, rate limiting, and delivery tracking.
Retrieval-augmented generation demos look great. Production RAG is a different engineering problem — chunking, hybrid retrieval, reranking, evaluation, and the failure modes nobody mentions at conferences.
A deep dive into the three dominant API paradigms — REST, GraphQL, and gRPC — covering design principles, pagination strategies, versioning, authentication patterns, and practical guidance on choosing the right one for your system.
A comprehensive guide to event-driven architecture — covering pub/sub, event sourcing, CQRS, saga patterns, message broker trade-offs, and the hard lessons teams learn in production.
A practical comparison of the vector databases people actually deploy in 2026 — and an honest look at when a vector database is the wrong tool for the job.
A deep dive into caching patterns that power the world's fastest systems — from cache-aside and write-through to multi-level architectures, stampede prevention, and real-world eviction strategies at scale.
Idempotency keys are what separate a payment system that double-charges during a retry from one that doesn't. The mechanism looks simple and has five subtle failure modes you need to know about.
Cut through the hype and understand when a monolith, modular monolith, or microservices architecture is the right fit. Covers service boundaries, data ownership, communication patterns, and practical migration strategies.
Understand how database indexes work under the hood, from B+ tree internals to composite index design. Learn to read EXPLAIN plans, avoid common anti-patterns, and make informed trade-offs between read performance and write amplification.
LLM-powered pipelines break in the same ways old monoliths did — when you stack synchronous calls. Queues, events, and the patterns that make a six-step AI pipeline survive a partial outage.
A complete system design walkthrough for building real-time chat at scale — covering WebSocket management, message delivery guarantees, presence systems, group chat fan-out, and end-to-end encryption.
A deep dive into the CAP theorem — what it really means for distributed systems, why you can only pick two guarantees, and how real databases like Cassandra, MongoDB, and DynamoDB make their trade-offs.
Three patterns for multi-tenant data isolation in SaaS, the trade-offs between cost, blast radius, and compliance, and a migration path from one to another when you outgrow your first choice.
A complete walkthrough of designing a URL shortener service — covering hashing strategies, database schema, caching, analytics, and scaling to billions of redirects.