Intro to System Design

Understanding large-scale system architecture

Understanding System Design Interviews

Why do companies do system design interviews? What are they looking for?

What Companies Are Looking For

This round often determines your level and assesses your ability to design large-scale, scalable, reliable, and maintainable software systems.

  • Ability to deal with ambiguity — Determine how much direction an engineer will need
  • Assess technical depth — On topics relevant to the job
  • Validate the candidate's resume — Does their demonstrated level of skill/expertise match their resume?
  • Test focus on business/customer impact — Understanding real-world constraints
  • Test communication and organizational skills — Can you explain complex systems clearly?

What They're Evaluating

1. Technical Architecture Skills

Can you break down a complex problem? Companies want to see if you can decompose a product or service into individual components like APIs, databases, caches, queues, etc.

Can you make trade-offs? Choosing between SQL vs. NoSQL, or consistency vs. availability (CAP theorem).

2. Scalability and Performance Awareness

Can your system handle scale? Think millions of users, high throughput, low latency.

Do you understand bottlenecks and how to mitigate them? Load balancing, partitioning, replication, etc.

3. Communication and Collaboration

Can you communicate your design clearly? Explaining concepts to stakeholders (PMs, other engineers) is crucial.

Are you open to feedback and iteration? It's not just about having a perfect design — it's about refining it collaboratively.

4. Real-World Engineering Judgment

Do you apply practical, not theoretical, knowledge? For example, designing a notification system that prioritizes user experience under high load.

Can you anticipate edge cases and failures? Handling server crashes, data loss, retries, rate limiting, etc.

5. Problem-Solving at the Systems Level

Can you innovate under constraints? Budget limits, data consistency requirements, or tight latency SLAs.

How do you approach new or unfamiliar domains? They want to see structured thinking even if the domain is new to you.

In short: System design interviews test your ability to be a "tech lead" or senior engineer — someone who can design solutions that work at scale, are maintainable, and meet business goals.

Note: The bar is raising — sometimes junior and mid-level folks get asked these now.

What is different about a system design interview compared to a coding interview?

  • The output is a design document rather than a fully implemented solution
  • The problems are intentionally underspecified
  • There is often no one best answer — there is a range of good answers depending on what parameters and priorities you set during the exploration phase
  • There are pros and cons to every decision and solution

Exploration of Systems

What IS a system?

  • Application or infrastructure that achieves user or business goals
  • Complex systems are constructed through a connected network of simpler systems (components)
  • These simpler systems are made up of still simpler components

System Design Interview Steps

1. Clarify Requirements (8-12 minutes)

Objective: Understand the problem and what is being asked. Ask clarifying questions to make sure you know exactly what the system needs to do.

Action: If the problem is broad, narrow it down. For example, if you're asked to design a "social media platform," clarify things like: "Are we focusing on newsfeed? Messaging? Scaling?" etc.

Key Questions to Ask:
  • Clarify assumptions:
    • Can we assume we have a 3rd party authentication system?
💡 Important Note:

In a system design interview, you don't ask "What are the functional requirements?" or "What are the non-functional requirements?" These are things you as the interviewee are expected to determine and clarify during the discussion.

Your job is to identify what the system needs to do (functional) and how well it needs to perform (non-functional) through your analysis and questions about the problem.

Why Functional Requirements Must Come Before Non-Functional Requirements

1. Functional Requirements Define What the System Does

Functional requirements describe the core behaviors and features of a system — the "what".

Examples:

  • Users can upload and share images
  • Admins can ban users
  • The system sends an email when a comment is posted
  • The service allows search over product listings
2. Non-Functional Requirements Describe How Well It Does That

Non-functional requirements describe the quality attributes of the system — the "how well" or "under what constraints".

Examples:

  • The system must handle 10,000 concurrent users
  • Latency must be under 200ms for 95% of requests
  • System must be available 99.99% of the time
  • Data must be eventually consistent within 5 seconds
3. Non-Functional Requirements Are Dependent On Functional Context

You can't say "the system must be available 99.99% of the time" unless you know:

  • What services are being used?
  • What are the critical user flows?
  • What is the expected workload?
  • What operations matter most?
Example:

Functional: "Users can submit payments"

Non-functional: "Payments must process in <1 second with 99.9% success rate"

Without knowing the function (payment submission), the performance goal (1s) is meaningless.

Back-of-the-Envelope Estimates

In a system design interview, "back-of-the-envelope" estimates are canonically part of the clarifying phase.

Purpose:
  • Determine scale: How many users? How much traffic? How big is the dataset?
  • Set realistic boundaries: Are we designing for 1M users or 1B?
  • Decide trade-offs: Do we need to optimize for cost, latency, availability?
Interviewer expects:

"Before diving into design, let's estimate how much traffic we're dealing with..."

Examples of Early Estimation Questions:
  • QPS (queries per second) — Read vs. write load
  • Data size — How much data we're storing per day, month, year
  • Latency targets — What's acceptable for the user
  • Storage needs — e.g., 1B URLs × 10 bytes each = ~10 GB raw
These estimations guide architectural choices like:
  • SQL vs NoSQL
  • In-memory cache size
  • Sharding strategy
  • Message queue durability
Role in High-Level Design:

Once your estimates shape the problem size, you can reference them in your high-level design:

  • "Because we expect 100M reads/day and 10M writes/day, I'm adding a read replica for scaling."
  • "Given our data set will grow to 1TB/year, I'm choosing S3 for object storage."

2. High-Level Design (10-15 minutes)

Objective: Start sketching the system's high-level architecture.

Action: Identify major components, how they interact, and how data flows. Consider the trade-offs between components (e.g., SQL vs. NoSQL databases). Also, bring up any assumptions you might be making.

3. Low Level Design (Component Design) (10-15 minutes)

Objective: Dive into individual components or subsystems of the architecture.

Action: Pick one or two critical parts of the system and design them in detail. For example, if you're designing a messaging system, you could focus on message storage, delivery guarantees, and scaling. Explain the protocols, APIs, and data models you would use.

4. Scaling and Performance Considerations (5 minutes)

Objective: Address scalability, availability, and reliability.

Action: Discuss how your system will scale horizontally and vertically. Consider potential bottlenecks (e.g., database, network, etc.), data sharding, caching strategies, load balancing, and failover strategies.

5. Trade-offs (5 minutes)

Objective: Discuss trade-offs in design decisions and how to mitigate potential bottlenecks.

Action: For instance, if you've chosen a certain database type, explain why you chose it and what trade-offs were involved (e.g., SQL vs. NoSQL). Also, talk about how you'd handle potential issues, such as system outages or data consistency challenges.

More Complex Examples: Discuss trade-offs like eventual consistency (social media likes - okay if delayed) vs. strong consistency (banking transactions - must be immediate), synchronous (user login - wait for response) vs. asynchronous processing (email notifications - send in background), or caching strategies (write-through vs. write-behind vs. cache-aside).

6. Conclusion / Q&A (5 minutes)

Objective: Summarize your system design and answer any final questions.

Action: Be prepared to summarize your system in 2-3 sentences and have thoughtful questions ready for the interviewer. Demonstrate your understanding by asking about potential edge cases, scaling considerations, or alternative approaches they might consider.

Pro Tips

  • Prioritize: Focus on the most important aspects of the system based on the problem's complexity. You might not have time to design every component in detail, so choose wisely where to dive deeper.
  • Explain Clearly: Always try to communicate clearly and succinctly. If you're running out of time, be honest and move on to the next section, but make sure you've covered the most critical aspects of the system.
  • Think Aloud: Interviewers are not just looking for the correct answer but also your problem-solving approach. Talk through your reasoning, so they can follow your thought process.
  • Time Allocations: 45 minutes (Meta), 60 minutes (Google)
  • Mindset: Treat the interviewer as your senior colleague — not setting traps for you
  • Tools: Get good at using Excalidraw for diagrams

How to Succeed as a Candidate

  • Clarify the requirements and scope of the problem
  • Make sure no major pieces of the problem are missing - you need the complete user flow, API endpoints, and data model for all functional requirements
  • Remember: it can be gamed just like the ACT, SAT, LSAT, GRE and leetcode

Key System Design Concepts

💡 Critical Practice Tip

Don't just study these concepts theoretically! You must create tiny projects using these technologies. If you rely purely on academic knowledge, you'll fold when the interviewer presses for implementation details or tries to poke holes in your plan.

Real hands-on experience is what separates candidates who can talk the talk from those who can walk the walk.

Candidates who show they can walk, better yet run, are the ones who get the job.

Database Types

1. Relational Databases (SQL)

Examples: PostgreSQL, MySQL, Microsoft SQL Server, Oracle

Key Features:

  • Structured data with schemas
  • Strong consistency (ACID transactions)
  • Use SQL for querying
  • Support joins, foreign keys, constraints

When to Use: You need complex queries and relationships (e.g. banking, ecommerce)

2. NoSQL Databases

Types:

  • Key-Value: Redis, DynamoDB (fast lookups, caching)
  • Document: MongoDB, Couchbase (JSON documents, flexible schemas)
  • Column-Family: Cassandra, HBase (high write throughput)
  • Graph: Neo4j (relationships, social networks)

When to Use:

  • Unstructured data
  • High scalability needs - canonically designed to spread data across many servers so easier to shard and replicate
  • High write throughput, especially at large scale - They can acknowledge writes faster by not waiting for all replicas to confirm since many NoSQL systems use eventual consistency (vs. strong consistency in SQL). Some NoSQL systems (like Cassandra or HBase) use Log-Structured Merge Trees (LSM), which batch and sequentially write data to disk — very fast for high-ingestion workloads

Caching

Key Concepts
In-memory caches:

Redis, Memcached

Use Cases:

Session storage, page caching, database query results

Eviction Policies:

LRU, LFU, FIFO

Cache Invalidation:

Write-through, write-back, TTL

Monitoring:

Hit/miss rate, eviction count, latency, memory usage

Use Cases
  • Reduce latency and database load
  • Store frequently accessed or expensive-to-compute data
  • Session management and authentication
  • CDN-based asset delivery

Message Brokers (Traditional Queues)

Examples: RabbitMQ, Amazon SQS, ActiveMQ

Messages are typically sent to a queue, where they are stored until consumed.

Each message is delivered to a single consumer (point-to-point).

Often supports features like message acknowledgments, retry, dead-letter queues, and priority queues.

Good for task queues, background job processing, and decoupling microservices.

Event Streaming Platforms (Distributed Logs)

Examples: Apache Kafka, Amazon Kinesis

Data is written to a topic, which acts as a durable, append-only log.

Each topic is split into partitions, which enable parallelism and scaling.

Multiple consumers can read from the same topic independently, enabling pub/sub and fan-out architectures.

Consumers track their position using an offset, allowing replay and fault recovery.

Excellent for event sourcing, real-time analytics, and data pipelines.

Pub/Sub Systems

What it is: A messaging pattern where publishers emit messages to a topic, and multiple subscribers independently consume them.

Common Systems: Google Pub/Sub, Kafka, Redis Pub/Sub

Key Concepts: Fan-out, durable vs. ephemeral subscriptions, push vs. pull

Relation to Event Streaming: Kafka is a pub/sub system under the hood.

Distributed Logs

What it is: An append-only, immutable log shared across distributed nodes.

Example: Kafka is a distributed log.

Relation to Event Streaming: Event streaming platforms are distributed logs; used for replaying events, CDC (Change Data Capture), etc.

Task Queues & Job Schedulers

What it is: Systems that manage background jobs and retries

Examples: Celery

Relation to Message Brokers: Message brokers like RabbitMQ or SQS are often used as underlying transport.

Event-Driven Architecture

What it is: A design style where services react to events instead of API calls

Key Concepts: Event producers, consumers, event store, eventual consistency

Relation to Messaging: Messaging systems are the core of EDA. Events flow through message brokers or streaming platforms, enabling services to react asynchronously to changes in the system. This decoupling allows for scalable, resilient architectures where services don't need to know about each other directly.

CAP Theorem

CAP Theorem states that in any distributed system, you can only guarantee two out of the following three properties at any given time:

C - Consistency

Every read receives the most recent write or an error. All nodes see the same data at the same time.

A - Availability

Every request receives a non-error response, even if it's not the latest data. The system is always responsive.

P - Partition Tolerance

The system continues to operate despite network failures or message delays between nodes.

⚠️ The Key Constraint

You must tolerate partitions in a distributed system — network failures are inevitable. So, in reality, you are forced to choose between Consistency vs. Availability when a partition occurs.

Classic Trade-offs:
  •  
  • CP: HBase, MongoDB (w/ config) — Prioritizes consistency, may reject reads/writes during partition.
  • Example: Banking systems — must show accurate balance even if it means rejecting some requests during network issues
  • MongoDB CP Configuration: Write concern set to "majority" — ensures writes are acknowledged by a majority of nodes. Read concern set to "majority" or "linearizable" — ensures reads return data that has been acknowledged by a majority of nodes or is fully consistent. By default, MongoDB is more AP (Available and Partition-tolerant), but with proper configuration, it can be tuned to prioritize consistency at the cost of availability — hence CP (Consistent and Partition-tolerant).
  • HBase CP Characteristics: HBase ensures strong consistency for both reads and writes. When a write is acknowledged, it is guaranteed to be visible in subsequent reads — even across distributed nodes. Built on top of HDFS (Hadoop Distributed File System), it's designed to tolerate network partitions. During a partition or failure (e.g. if a region server goes down), HBase may reject reads/writes until it can ensure consistency through recovery or leader election.
  • CP Partition Handling: When a network partition occurs (i.e., parts of the cluster can't talk to each other), a CP system like HBase must choose between consistency and availability. Because HBase prioritizes consistency, it chooses to reject operations (reads or writes) if it cannot guarantee that they are consistent.
    • Writes: If a partition causes a region server or HMaster to become unreachable, HBase may refuse writes to that region until leadership is re-established, the system can confirm that no conflicting writes occur, or data can be safely replicated or persisted.
    • Reads: Similarly, if the system cannot guarantee that a read would return the latest consistent state, it may reject the read request rather than return stale or potentially incorrect data.
  •  
  • AP: Couchbase, Cassandra — Always responds (available), may return stale data. You might get an outdated (not latest) value when reading data. Systems like Cassandra and Couchbase are designed to be AP under the CAP theorem, meaning: A = Availability: They try to always respond to read/write requests, even during network partitions or node failures. P = Partition tolerance: They continue functioning even if parts of the network can't communicate. But to maintain availability, they sacrifice consistency, especially during failures or partitions.
  • Example: Social media feeds — better to show slightly old posts than no posts at all
  • AP Example with Cassandra: Imagine you're writing value = 42 to key x. That write goes to Node A. At the same time, Node B, which hasn't received that update yet due to a partition, gets a read request for key x. Cassandra will still serve the read from Node B — it won't block or fail. But since Node B hasn't seen the latest write (value = 42), it may return an older value, like value = 30. This is stale data — it's outdated, not the latest write.
  •  
  • CA: Only in theory (no partition) — Not practical in real-world distributed systems

Transactions & ACID Properties

A transaction is a sequence of one or more operations that are treated as a single, indivisible unit of work. Either all operations complete successfully, or none of them do.

ACID Properties
  • Atomicity: All operations must complete fully or have no effect (all or nothing)
  • Consistency: Database must move from one valid state to another valid state
  • Isolation: Transactions run independently — intermediate steps not visible to others
  • Durability: Once committed, changes persist even if there's a crash
Example: Banking Transfer

Imagine transferring $100 from Account A to Account B:

  1. Read balance of A
  2. Subtract $100 from A
  3. Add $100 to B
  4. Write updated balances

If the system crashes after step 2, the transaction rolls back to prevent data loss.

Race Conditions

A race condition occurs when two or more operations happen concurrently, and the final outcome depends on the non-deterministic timing or order of their execution.

Example: Two users withdraw from same account
User 1: Read balance: $100
User 2: Read balance: $100 (same time)
User 1: Withdraw $80 → Balance: $20
User 2: Withdraw $80 → Balance: $20 (overdraft!)

Expected: $100 - $80 = $20 (only one withdrawal)
Actual: Both withdraw $80, ending with -$60

Solution: Use transactions with proper isolation levels, locks, or optimistic concurrency control.

Key Contexts Where Race Conditions Arise

  • Databases: SQL transactions vs NoSQL conditional writes
  • Caches: Cache stampede, race between DB write and cache set
  • Distributed Systems: Multiple services updating shared state
  • Queues: Multiple workers picking the same task
  • File Storage: Parallel uploads, version conflicts
  • Authentication: Login/logout races, token refresh

Process vs Thread

Process

A process is an independent program in execution. It has:

  • Its own memory space (code, data, stack, heap)
  • Own resources (file handles, network connections, etc.)
  • At least one thread (called the main thread)

Think of it as: A fully isolated container running a program.

Thread

A thread is the smallest unit of execution within a process:

  • Threads in the same process share the same memory and resources
  • Multiple threads can run concurrently in the same process
  • Cheaper to create and switch between than processes

Think of threads as: Workers inside the same container doing different tasks but sharing tools.

Concluding Thoughts

1. Data Models vs APIs

In a system design interview, you typically define APIs after you understand the data models, but the process is iterative. Here's the breakdown:

"Let's define the core data models first so we know what entities the APIs need to interact with. Once we have a sense of the relationships and structure, we can define clean APIs around them."

That shows structured thinking and interviewers like it.

Sometimes defining an API leads you to adjust a model.

Example: Designing POST /checkout might make you realize you need a Cart or Transaction entity that wasn't in your initial model.

Why data models often come first:

  • Data models represent the core of your system: users, posts, products, etc.
  • They reflect the business logic and relationships.
  • You can't design meaningful API inputs/outputs without understanding what data needs to be stored and retrieved.

Example: If you're designing a ride-sharing app:

You need to define models like User, Ride, Driver, Location before deciding on APIs like:

  • POST /rides
  • GET /users/{id}/rides

Define core data models / entities in the high level design portion of the interview.

High-Level Design (HLD): Key components, major interactions, core data models (at least basic entities), and rough API boundaries

Low-Level Design (LLD): Detailed schema, indexing, table structure, API request/response formats, protocol details, error handling

2. Steering to Your Strengths

Can you steer the interviewer to your strengths? Yes — absolutely, and it's a smart move.

How to do it effectively:

  • Signal it explicitly, but professionally.
  • "There are many pieces to this system — I'd love to go deeper into the caching layer or the async processing part, since that's where I've spent most of my time."
  • Still acknowledge the other areas.
  • Give a quick high-level sketch of the parts you're less strong in before shifting focus.
  • This shows breadth without risking depth in weak areas.

If you're strong on storage design:

"We can briefly sketch the API layer, but I'd love to dive into how we model the data, choose the database, and handle writes under load."

Interviewers want signal, not a perfect system.

Driving the conversation where you're strongest is a great way to demonstrate value.

Just don't completely dodge weak areas — show awareness even if you keep it high level.

3. Interview Strategy

Key Principles:

  • Show structured thinking — break down complex problems systematically
  • Demonstrate practical knowledge — reference real technologies and trade-offs
  • Communicate clearly — explain your reasoning as you go
  • Be honest about limitations — acknowledge areas you're less familiar with
  • Focus on the most critical aspects — don't get lost in details

Remember: The goal isn't to build a perfect system, but to show you can think through complex problems, make reasonable trade-offs, and communicate your approach effectively.

Practice these concepts with real projects, and you'll be well-prepared for system design interviews.