I spent months pulling apart how real companies build their systems. Not the polished conference talks or the "we use microservices" blog posts. The actual architectures, pieced together from engineering blogs, open-source repos, incident reports, and a frankly unhealthy amount of infrastructure spelunking.
A reference architecture is a model of how a real production system fits together — its services, data stores, queues and failure boundaries — reconstructed from public sources so other engineers can copy the reasoning instead of the logo.
The result is 55 interactive architecture diagrams, all available in the Codelit template library, alongside 90+ templates you can generate from a plain-English prompt. But the diagrams aren't the interesting part. The patterns are.
Everyone Uses Message Queues. Everyone.
Of the 55 architectures I studied, 51 use some form of asynchronous message passing: Kafka at scale (Uber, Netflix, LinkedIn, Spotify), SQS in AWS-native shops, RabbitMQ in older systems that haven't migrated.
I'm not exaggerating about the "everyone".
The pattern is always the same. Decouple the thing that receives requests from the thing that processes them. It sounds obvious out loud. But I still see engineers building synchronous request chains across 6 services and wondering why everything falls over when one goes down.
If you're designing a system and you don't have a queue somewhere, you're probably building a monolith (which is fine) or you're going to have a bad time (which isn't).
Why Is Caching the #1 Scaling Tool?
Caching is the biggest scaling win across the 55 architectures I studied, because a cache removes work from the system while every other option just adds capacity to absorb the same work. Not microservices. Not Kubernetes. Not that fancy service mesh you've been eyeing.
Caching.
Instagram serves 2 billion+ users. Their architecture? Memcached. A lot of Memcached. The read path is: check cache → return if hit → query Postgres if miss → populate cache → return. That's basically it.
Netflix caches at every layer: CDN edge, API gateway, service-level, database query cache. Their EVCache system handles 30 million requests per second. Thirty million. Per second.
Before you reach for a new service, a new database, a new anything, ask whether a cache solves it.
How Does Stripe Make Every Payment Safe to Retry?
Stripe makes every payment safe to retry with client-generated idempotency keys. The client sends a unique key with the request, and Stripe guarantees the same key always produces the same result, so a retry after a dropped connection cannot double-charge anyone.
I expected Stripe's architecture to be impossibly complex. It's not. It's one good idea — dual-write with idempotency keys — applied everywhere. No double charges. No lost payments.
POST /v1/charges
Idempotency-Key: user_abc_order_123_attempt_1
{
"amount": 2000,
"currency": "usd",
"source": "tok_visa"
}
If the network drops mid-request, the client retries with the same key. Stripe sees the key, returns the cached result. Simple. Reliable. The kind of design that makes you think "why doesn't everyone do this?"
(Everyone should do this.)
Uber Is the Most Complex System I Studied
Uber's real-time matching system is the most complex architecture in the set: it has to pair riders with drivers across millions of concurrent users while location data streams in continuously, and every bit of that complexity is earned.
The architecture involves:
- Geospatial indexing with Google S2 cells to efficiently query "which drivers are near this rider"
- WebSocket fan-out to push updates to drivers in real-time
- Ring buffers for location data (you only care about the last N positions)
- Consensus protocols to handle the "two riders request the same driver" problem
The diagram took me three iterations to get right. I drew it by hand rather than running it through the pipeline that turns a prompt into a diagram, because drawing a system yourself is how you find the parts you don't actually understand. It's also the most popular diagram in the template library — engineers love it because it combines so many patterns in one system.
Why Does Netflix Push Content Before You Ask for It?
Netflix pushes content to edge servers before anyone requests it because prediction is cheaper than a cache miss. Open Connect analyses viewing patterns, forecasts what will be popular in each region, and pre-positions files on ISP-embedded servers during off-peak hours.
Most CDNs work the other way: request → check → miss → fetch from origin → cache → serve.
By the time you click play on that new show, it's already sitting on a server in your ISP's data center. The latency is essentially local network speed.
The prediction model isn't even sophisticated. New releases get pushed everywhere. Popular shows get pushed to regions where they're trending. The 80/20 rule does the heavy lifting: 80% of views come from 20% of content, and that 20% is predictable.
When Do You Actually Need WebSockets?
You need WebSockets when the server has to push updates the client cannot predict — which is exactly Discord's problem, with millions of simultaneously connected clients waiting on messages that arrive whenever somebody else decides to type.
A lot of engineers default to WebSockets when polling would work fine. Discord is one of the few cases where you genuinely need them.
Their Elixir-based gateway holds ~1 million WebSocket connections per server. Messages fan out through a pub/sub layer — their own implementation, not Redis pub/sub, because the overhead was too high at their scale.
The interesting bit: "lazy guilds." When you connect, Discord doesn't load all your servers' data. It loads a lightweight summary, then fetches the rest only when you navigate to a server. This cut their initial connection payload by 90%.
Spotify's Microservices (Done Right)
Spotify runs ~800 microservices, but it didn't start there. The company began as a monolith and split along team boundaries as it grew, with each squad owning its services end-to-end.
The pattern that works: services communicate through an event bus (Kafka), not direct HTTP calls. If the recommendation service goes down, playback keeps working. They're decoupled in code and in failure modes — which is exactly what the chaos mode I built to break diagrams on purpose tests for, because nobody finds out whether their services are really decoupled until something dies at an inconvenient hour.
What Is the Most Common System Design Mistake?
The most common system design mistake is routing every service through a single API gateway, which turns one component into a shared point of failure, a throughput bottleneck, and a deployment chokepoint for unrelated teams.
I see this in probably 70% of system design interview answers. Every change to any service ends up needing a gateway redeploy or reconfigure. Watching engineers work through it is most of what taught me how people actually learn system design, and the gateway is always drawn first and questioned last.
What works at scale: multiple gateways organized by domain. Spotify has separate gateways for playback, search, and social. Uber has separate gateways for rider-facing and driver-facing APIs. A gateway deployment for search doesn't risk taking down playback.
What Actually Scales, and in What Order?
Read replicas plus caching handle about 90% of real scaling needs, asynchronous queues handle the next 8%, and sharding covers the 2% that genuinely needs it. That order held across all 55 architectures.
| Scaling strategy | What it actually solves | Share of scaling needs | Where it breaks |
|---|---|---|---|
| Read replicas + caching | Read-heavy load, repeated queries | ~90% | Write-heavy workloads, invalidation you got wrong |
| Async processing with queues | Slow work blocking the request path | The next 8% | Ordering guarantees, backlog during an incident |
| Sharding / partitioning | A dataset one machine can't hold | The remaining 2% | Cross-shard queries, rebalancing |
| Microservices | 200 engineers in one codebase | Organisational, not technical | Shared databases, which restore the coupling you split to remove |
That last row is controversial, but I'll stand by it. Microservices solve the "200 engineers on the same codebase" problem. They don't solve "we need to handle more traffic". Read replicas and caching solve that.
Sharding is also the row that shows up on the invoice first, which is roughly why I built an estimator that prices an architecture before you build it. A partition strategy is a billing decision wearing an engineering hat.
Airbnb, Tinder, Slack: Quick Hits
Airbnb, Tinder and Slack all turned out to be far plainer than their reputations suggest: tuned Elasticsearch, geospatial queries over a partitioned database, and channel-level sharding respectively.
| System | What the architecture actually is | The part that surprised me |
|---|---|---|
| Airbnb search | Elasticsearch with a custom scoring layer | Scoring weighs price, location, reviews, host response time, listing quality. Nothing exotic. |
| Tinder matching | Geospatial queries on a partitioned database | The swipe structure is a Redis sorted set per user. The complexity is in the recommendation algorithm, not the infrastructure. |
| Slack messaging | Channel-based sharding, one partition per channel | Typing indicators are heartbeat messages over WebSockets, throttled to one per 3 seconds. |
Deceptively simple, all three. That is the compliment it sounds like.
How Do You Study an Architecture You Didn't Build?
The fastest way to study an architecture you didn't build is to make it clickable. All 55 of these live in Codelit as interactive diagrams, where you can select any node and see what it does, why it's there, and what would break if you removed it.
That is the entire reason I built Codelit after a Lucidchart rage-quit. Static diagrams let you look at a system, and looking at a system teaches you almost nothing.
Pretty pictures are not the point. The "why" is. Why does Uber use WebSockets but Airbnb doesn't? Why does Netflix push to the edge but Spotify streams on demand?
Explore all 55 architectures and poke around. Drag things. Break things. That's how you learn.
The Meta-Lesson
The meta-lesson from 55 architectures is that the best ones aren't clever, they're boring: well-understood patterns — caches, queues, read replicas — composed thoughtfully. The "genius" isn't in the individual components. It's in knowing which problems to solve and which to avoid.
Every time I found a system that felt overly complex, I could trace it back to one of two causes: solving a problem they didn't actually have, or not solving a problem early enough and having to bolt on a fix later.
Build the simple thing. Add complexity only when the simple thing breaks. And when it does break, check if a cache fixes it first.
It usually does.
Questions people actually ask
- What do most real-world system architectures have in common?
- Almost all of them run on asynchronous message passing and aggressive caching. Of the 55 production architectures I studied, 51 use a queue or event bus of some kind, usually Kafka at large scale and SQS in AWS-native shops. Caching then does most of the remaining scaling work. The components are ordinary. What separates the good systems is judgement about which problems to solve at all.
- Do I really need a message queue in my architecture?
- If your system has work that does not have to finish before you reply to the user, yes. A queue decouples the component that accepts a request from the component that does the work, so one slow dependency cannot drag down the whole chain. The main exception is a monolith, which is a perfectly reasonable place to start and does not need one until it stops being reasonable.
- Is caching or microservices better for scaling?
- Caching, by a wide margin, because the two solve different problems. Read replicas plus caching handle roughly ninety percent of real scaling needs. Microservices solve organisational scaling, letting two hundred engineers work without stepping on each other, and they do not by themselves make a system absorb more traffic. Instagram serves billions of users largely on Memcached, and Netflix runs caches at every layer of its stack.
- What is an idempotency key and why does Stripe use one?
- An idempotency key is a unique string the client generates and sends with a request so the server can recognise a repeat of the same operation. Stripe attaches one to every payment request. If the network drops mid-call, the client retries with the same key, Stripe returns the original result instead of charging again, and nobody gets billed twice. It is the cheapest reliability primitive in payments.
- What is the most common system design interview mistake?
- Routing everything through a single API gateway. It looks tidy on a whiteboard, and it creates one component that is simultaneously a single point of failure, a throughput bottleneck, and a deployment chokepoint for teams with nothing to do with each other. Large systems split gateways by domain instead. Spotify runs separate gateways for playback, search and social. Uber separates rider-facing and driver-facing APIs.
- Where can I find real-world architecture diagrams to study?
- All 55 of these architectures are published as interactive diagrams in the Codelit template library, alongside more than ninety templates you can generate from a plain-English prompt. Every node is clickable, so you can see what a component does, why it is there, and what would break without it, then drag things around or export the whole diagram to Mermaid or infrastructure code.