System Design
15 System Design Building Blocks You Should Know
Every large system, no matter how different, is assembled from the same handful of components. Master these fifteen building blocks and you can design almost anything by combining them.
Here's a secret that makes system design far less intimidating: every large system you'll ever be asked to design - a social network, a ride-sharing app, a video platform, a payment system - is assembled from the same small set of building blocks. The systems look wildly different on the surface, but underneath they're combinations of the same components, arranged to fit the problem.
Learn these fifteen building blocks well, and system design transforms from "invent something from nothing" into "choose and combine the right components." This guide is your map of those blocks - what each does and when you reach for it. Many have full dedicated deep-dives; this is the overview that ties them together.
graph TD
C[Client] --> DNS[DNS] --> LB[Load Balancer]
LB --> APP[App Servers]
APP --> CACHE[Cache]
APP --> DB[(Database)]
APP --> Q[Message Queue]
CDN[CDN] --> C
DB --> REP[(Replicas)]
This diagram shows several building blocks working together. A client uses DNS to find a load balancer, which distributes requests to app servers. The app servers read from a cache and a database, and send work to a message queue. A CDN serves content to the client, and the database has replicas. These are some of the fifteen building blocks assembled into a typical system.
1. Load Balancer
Distributes incoming requests across multiple servers so no single one is overwhelmed. The foundation of horizontal scaling and high availability - it spreads load evenly and routes around failed servers via health checks.
You reach for it when: you have more than one server and need to distribute traffic. Essentially every scalable system has one.
2. Cache
Stores frequently accessed data in fast memory so the system doesn't repeat expensive work. A cache hit returns data in microseconds instead of querying a database. Caching can live at many layers - in front of the database, in the application, at the edge.
You reach for it when: the same data is read repeatedly, or expensive computations are requested often. It's the single highest-leverage performance tool, especially for read-heavy systems.
3. CDN (Content Delivery Network)
A globally distributed network of servers that cache content close to users. A request from Tokyo is served from a nearby edge server rather than a distant origin, defeating the latency of physical distance.
You reach for it when: you serve static content (images, video, scripts) or cacheable responses to a geographically distributed audience.
4. Database
The system's source of truth, where data is stored durably and queried. Choosing the right type - relational (SQL) for structured data with strong consistency, or NoSQL for scale and flexibility - is one of the core design decisions.
You reach for it when: you need to store and retrieve data reliably, which is almost always. The database is frequently the hardest part of a system to scale.
5. Database Replication
Keeping copies (replicas) of the database on multiple machines, both for reliability (if one fails, others survive) and performance (spread read queries across replicas). A primary handles writes; replicas handle reads.
You reach for it when: your database is a read bottleneck or a single point of failure. Read replicas are usually the first step in scaling a database.
6. Database Sharding
Splitting a database that's too big for one machine across many machines, each holding a slice ("shard") of the data. This is how you scale writes horizontally when a single database can't keep up.
You reach for it when: your data or write volume exceeds what one machine can handle. It's powerful but complex - adding the challenge of routing queries to the right shard.
7. Message Queue
A buffer that holds messages between a producer and a consumer, decoupling them. The producer drops a message and moves on; the consumer processes it when ready. Queues absorb traffic spikes and enable asynchronous processing.
You reach for it when: you need to decouple components, process work asynchronously, or smooth out bursts of load. Essential for moving slow work out of the request path.
8. API Gateway
A single entry point that sits in front of your services, handling cross-cutting concerns - authentication, rate limiting, routing, request aggregation - so individual services don't each reimplement them.
You reach for it when: you have multiple services (microservices) and need a unified front door that centralizes shared concerns.
9. Reverse Proxy
A server that sits in front of your backend servers and forwards client requests to them, hiding and shielding the backends. It can handle SSL termination, caching, and compression. (Load balancers and API gateways are specialized reverse proxies.)
You reach for it when: you want to front your servers with a layer that adds security, performance, and a single point of control.
10. DNS (Domain Name System)
Translates human-friendly domain names into the network addresses of servers. It's the first step in nearly every request - and it can also do load balancing by directing different users to different servers or regions.
You reach for it when: always - it's fundamental infrastructure. It also plays a role in directing traffic across regions for global systems.
11. Blob / Object Storage
Storage designed for large unstructured files - images, videos, backups, documents. Rather than storing big files in a database (which is inefficient), you store them in object storage and keep just a reference in the database.
You reach for it when: you handle large files or media. Object storage is built to hold vast amounts of unstructured data cheaply and durably.
12. Search Index
A specialized data structure (and often a dedicated system) that makes searching through large amounts of data fast. Databases aren't optimized for full-text search, so a search index handles queries like "find all posts containing these words" efficiently.
You reach for it when: users need to search through text or you need fast, flexible queries that a regular database handles poorly.
13. Rate Limiter
Caps how many requests a client can make in a time window, protecting your system from overload, abuse, and runaway costs. It decides, per client, whether to allow or reject each request.
You reach for it when: you need to protect services from being overwhelmed by too many requests - from abuse, bugs, or simple overload. Often built into the API gateway.
14. Monitoring and Logging
The system's observability layer - collecting metrics (how fast, how many, how many errors) and logs (records of what happened) so you can understand the system's health, debug problems, and plan capacity.
You reach for it when: always, in any production system. You can't operate or improve what you can't see, which makes observability non-negotiable - it's the difference between debugging with evidence and guessing in the dark.
15. Distributed Coordination Service
A specialized system (like ZooKeeper or etcd) that helps distributed components coordinate - agreeing on a leader, sharing configuration, managing which nodes are alive, and maintaining consistency across the cluster.
You reach for it when: you have a distributed system that needs nodes to coordinate - leader election, service discovery, distributed locks, or shared configuration.
How they fit together
The magic isn't in any single block - it's in how they combine. Consider a typical large web application and watch the blocks assemble:
A user's request starts at DNS, which resolves the domain to a load balancer. The load balancer distributes the request across application servers. Those servers check a cache first; on a miss, they query the database, which has read replicas to spread load and is sharded if the data is huge. Static content like images comes from a CDN and lives in object storage. Slow work (sending emails, processing uploads) is pushed onto a message queue for asynchronous handling. Search queries go to a search index. The whole thing sits behind an API gateway (or reverse proxy) that handles authentication and rate limiting. Monitoring and logging watch over everything, and a coordination service keeps the distributed pieces in agreement.
That's a complete, scalable architecture - and it's nothing but these fifteen blocks arranged to fit. Design almost any large system and you'll find yourself reaching for the same set, in different combinations.
Interview: This is the secret to system design interviews: you're not inventing components from scratch, you're selecting and arranging these building blocks to fit the problem. When you get "design X," walk through which blocks you need - "I'll need a load balancer, app servers, a cache because this is read-heavy, a sharded database, a CDN for the media, and a queue for the async work." Demonstrating that you know the building blocks and can combine them deliberately is exactly what interviewers are looking for.
A worked example: building a URL shortener
To see the blocks in action, let's design a simple system - a URL shortener (like bit.ly) - purely by selecting from the fifteen. A user submits a long URL and gets a short code; visiting the code redirects to the original.
- Requests arrive via DNS → a load balancer → application servers.
- The mapping of short code to long URL is stored in a database. Because this system is read-heavy (links are created once, visited many times), we put a cache in front, so popular links are served from fast memory without hitting the database.
- The database gets read replicas to spread the heavy read load, and if the number of links grows enormous, we shard it across machines.
- A CDN helps serve the redirects quickly to users worldwide.
- We add a rate limiter on the link-creation endpoint to prevent abuse, and monitoring to watch the system's health.
In one modest design, we naturally reached for seven or eight of the fifteen blocks - and we never invented a single new component. That's the point: design becomes assembly. The same exercise works for any system; you'd reach for object storage and a message queue for a video platform, a search index for a system with text search, a coordination service for a distributed database. The blocks are universal; the combination is what fits the problem.
The blocks you add as you scale
The building blocks also map onto a system's growth story. A tiny system might need only an app server and a database. As it grows, you add blocks in a recognizable order:
- A load balancer and more app servers - to handle more traffic by scaling out.
- A cache - to relieve the database as reads grow.
- Read replicas - to spread read load further.
- A CDN - to serve static content and reduce latency for distant users.
- A message queue - to move slow work out of the request path.
- Sharding - when the database's write volume outgrows one machine.
- Specialized blocks - a search index, object storage, an API gateway - as specific needs arise.
You rarely need all fifteen at once. They're added as the system grows and new bottlenecks appear, each block relieving a specific pressure. Recognizing which block solves the bottleneck you currently have is a core scaling skill.
Every block has a cost
It's worth remembering that each block solves a problem but introduces its own complexity - so you add them deliberately, not reflexively. A cache speeds reads but introduces staleness and invalidation challenges. Replication improves reads and availability but raises consistency questions. Sharding scales writes but complicates queries that span shards. A message queue decouples components but adds infrastructure to operate and reason about. An API gateway centralizes concerns but can become a bottleneck or single point of failure if not made redundant.
This is why you don't add every block to every system - you add a block when the problem it solves outweighs the complexity it brings. A small system with a cache it doesn't need is just more to operate. The art is adding each block at the right time: when the bottleneck or need it addresses has actually arrived. Matching blocks to genuine needs - rather than adding them because they're "best practice" - is what separates a clean, appropriately-scaled design from an over-engineered one.
How to use this list
Treat these fifteen blocks as your foundation. When you're learning system design, make sure you understand each one deeply - what it does, how it works, and its trade-offs. When you're designing, run through the list as a checklist: which blocks does this problem need, and how do they connect? When you're stuck on a design, often the answer is recognizing that you need a block you haven't added yet (a cache to relieve the database, a queue to decouple a slow step).
A practical way to internalize them is to take systems you already use - a chat app, a video platform, a ride-sharing service - and reverse-engineer which blocks they must contain. The chat app needs a message queue and real-time delivery; the video platform needs object storage and a CDN; the ride-sharing service needs geospatial indexing and real-time location updates. Doing this repeatedly trains your eye to see any system as a combination of these blocks, which is exactly the skill that makes designing a new one feel manageable rather than daunting.
Each block here has its own depth, and many have dedicated guides. But the fifteen together form a complete vocabulary - learn them, and you can read and design almost any system, because almost every system is built from these same pieces.
The bottom line
Every large system is assembled from the same small set of building blocks: load balancers, caches, CDNs, databases (with replication and sharding), message queues, API gateways, reverse proxies, DNS, object storage, search indexes, rate limiters, monitoring, and coordination services. The systems look different, but they're combinations of these fifteen components arranged to fit each problem.
Master these blocks individually, learn how they combine, and system design stops being intimidating - it becomes the craft of choosing and arranging proven pieces. The same fifteen components, recombined in different proportions, underlie systems as different as a social network and a payment processor - which is why mastering them generalizes to almost any design problem you'll face. We build deep familiarity with each block, and the judgment to combine them, across System Design Fundamentals.
Go deeper
- The System Design Primer - a comprehensive open-source walkthrough of these building blocks with examples.
- Designing Data-Intensive Applications - the definitive deep reference for the data-layer blocks.
- Amazon Builders' Library - how these components are built and operated at scale.
- Distributed computing (Wikipedia) - the foundations underneath the distributed blocks.