System Design: Introduction

Understand what system design means, why it matters at scale, and how to think through architectural decisions before writing a single line of code.

What is System Design?

System design is the process of defining the architecture, components, data flows, and interfaces of a software system to satisfy a given set of requirements. It sits between product requirements and actual implementation - the phase where you decide how the pieces fit together rather than what the pieces individually do.

When a company asks you to design Twitter, or a URL shortener, or a chat application, they are not asking you to write code. They want to see how you think about scale, reliability, data consistency, and trade-offs. Every decision you make - which database to use, whether to cache, where to place a load balancer - has consequences that compound at millions of users.

System Design vs Software Architecture

These terms overlap but are not identical. Software architecture is often about code-level structure: patterns like MVC, layers, modules. System design focuses on the infrastructure level: servers, databases, queues, CDNs, and how they communicate. In practice, senior engineers need both.

  • Software Architecture:How code is organized within a service. Concerns itself with design patterns, interfaces, and module boundaries.
  • System Design:How services, databases, caches, and networks are organized as a whole. Concerns itself with scale, latency, and fault tolerance.

Basic 3-Tier System Architecture

Introduction

Client sends requests to an API server, which reads from a cache for hot data or falls back to the primary database for a full read.

100%
Loading system design canvas…

High-Level Design vs Low-Level Design

System design conversations almost always split into two phases. The first is High-Level Design (HLD): you sketch the major boxes and the arrows between them. What are the core services? How does data flow from a client request all the way to a database write and back? You are not writing code here - you are drawing a map.

Low-Level Design (LLD) zooms into one of those boxes. You define the class structure, the API contracts, the database schema, the specific algorithms. LLD assumes HLD is settled. You cannot sensibly design a class hierarchy for a payment service if you have not yet decided whether payments are synchronous or processed via a queue.

HLD vs LLD at a Glance

  • HLD - Components:Services, databases, caches, CDNs, message queues, and load balancers.
  • HLD - Questions:How many services? How do they talk to each other? Where does state live? How do we handle failure?
  • LLD - Components:Classes, methods, database tables, indexes, API endpoint schemas.
  • LLD - Questions:What fields go in this table? What does this function return? How does pagination work in this endpoint?

In an interview, you will typically spend 70% of your time on HLD and only touch LLD for one or two specific components the interviewer finds interesting. Start wide, then go deep where it matters.

Functional vs Non-Functional Requirements

Before drawing a single box, you need to understand what the system is supposed to do and how well it needs to do it. These two categories of requirements shape every architectural choice that follows.

Functional requirements describe the features - what actions the system performs. Non-functional requirements describe the quality attributes - how fast, how reliable, how large, how secure. A system that handles all the features but crashes under load has failed its non-functional requirements. Both categories are equally real constraints.

Examples: URL Shortener

Consider a system that shortens URLs like bit.ly. Here is how the requirements split:

  • Functional:Given a long URL, return a unique short code. Given a short code, redirect to the original URL. Users can optionally create custom aliases.
  • Non-Functional (Scale):100 million URLs created per day, 10 billion redirects per day. Reads are 100x more frequent than writes.
  • Non-Functional (Latency):Redirect must complete in under 10ms at p99. URL creation can tolerate up to 500ms.
  • Non-Functional (Availability):99.99% uptime. The redirect service is more critical than the creation service.

Notice how those non-functional numbers immediately change the design. 10 billion redirects per day is about 115,000 requests per second at peak. That means you almost certainly need a distributed cache in front of your database - no relational database can sustain 115k reads per second without one. The non-functional requirements just told you to add Redis before you have even opened a code editor.

Back-of-the-Envelope Estimation

Good system designers do quick math before committing to an architecture. The goal is not precision - it is order-of-magnitude reasoning. You want to know whether you need one database or twenty, whether you need 1 GB of cache or 1 TB. Getting the estimate wrong by 2x is fine. Getting it wrong by 100x means you build the wrong thing.

A handful of numbers are worth memorizing. Storage: 1 million users, each storing an average of 100 KB of data, is 100 GB. Throughput: 1 million requests per day averages to roughly 12 requests per second. Latency: an SSD read takes about 0.1 ms, a database network round-trip takes about 1 ms, a cross-datacenter round trip takes about 50-150 ms.

Estimation Framework

Work through these four dimensions for any new system:

  • Traffic:Requests per day / 86,400 seconds = average RPS. Assume peak is 2-3x the average.
  • Storage:Daily new data = writes per second x object size x seconds. Multiply by retention period (e.g. 5 years).
  • Bandwidth:Ingress = write RPS x object size. Egress = read RPS x object size.
  • Cache:If 20% of data drives 80% of reads (Pareto), cache only that 20%. Size accordingly.

Run these numbers out loud in an interview. Interviewers care about the process as much as the result. Showing that you naturally reach for estimation before architecture demonstrates engineering maturity - you are designing for the actual load, not an imaginary one.

Trade-off Thinking

Every architectural decision involves giving something up. There is no perfect database, no universally correct caching strategy, and no network topology that is optimal for every workload. The engineer's job is to understand the trade-offs and make the choice that best fits the specific context.

The CAP theorem is the classic example: in a distributed system, you can only guarantee two of three properties - Consistency (every read sees the most recent write), Availability (every request gets a response), and Partition Tolerance (the system continues operating through network failures). Since network partitions happen in any real distributed system, you are always trading between consistency and availability.

Common Trade-offs in System Design

  • Latency vs Consistency:Writing to a single primary database is strongly consistent but slow. Writing asynchronously to replicas is fast but eventually consistent - a user may read stale data for a brief window.
  • Cost vs Performance:An in-memory cache (Redis) is 10-100x faster than a database read, but RAM is 5-10x more expensive per GB than SSD. Cache only what gets hit frequently.
  • Simplicity vs Scalability:A monolith is simpler to develop and deploy. Microservices scale specific components independently but introduce network latency, distributed tracing complexity, and operational overhead.
  • Read performance vs Write performance:Adding database indexes speeds up reads dramatically. Every additional index slows down writes because the index must be updated on every INSERT or UPDATE.

When you articulate a trade-off in an interview - for example, "I am choosing eventual consistency here because this is a social feed and slightly stale data is acceptable, whereas a payment system would require strong consistency" - you are demonstrating exactly the kind of judgment senior engineers are evaluated on.

A Repeatable Approach to System Design

Faced with an open-ended design prompt, most engineers freeze or jump straight to code. Neither is effective. The following sequence gives you a structured way to attack any problem without losing the thread.

6-Step Framework

  • 1. Clarify Requirements:Ask questions before drawing anything. What features are in scope? What is the expected scale? Any regulatory constraints? What does success look like in 3 years?
  • 2. Estimate Scale:Do the back-of-the-envelope math on traffic, storage, and bandwidth. These numbers constrain your architecture choices immediately.
  • 3. Define the API:Agree on the input and output of each core operation before deciding how to implement it. This keeps the design grounded in actual user needs.
  • 4. Sketch the High-Level Design:Draw the major components and data flows. Client, load balancer, application servers, cache, database, CDN if applicable. Keep it at the box-and-arrow level.
  • 5. Deep Dive on Critical Components:Pick the hardest or most interesting part - usually the component that has to handle the most load or the most strict consistency requirements - and go into detail.
  • 6. Identify Bottlenecks and Discuss Trade-offs:What breaks first under 10x load? Where is the single point of failure? What would you change if writes became 100x more frequent? Show that you think beyond the happy path.

This framework applies whether you have 20 minutes or an hour. The depth of each step scales with time. In a short session you might spend 5 minutes on estimation and 10 minutes on the high-level diagram. In a longer session you can go into database schema, sharding strategy, and failover behavior for individual components.

Knowledge Check

Knowledge Check

1. What is the primary goal of system design?

2. Which of these is a non-functional requirement?

3. High-Level Design (HLD) is primarily concerned with:

4. In a back-of-the-envelope estimation, you estimate that your system needs to handle 10,000 requests per second. Each request reads 1 KB of data. What is the approximate read throughput per day?

5. The CAP theorem states that a distributed system can guarantee at most two of three properties. Which three properties does it refer to?