system-design · beginner

System Design Foundations — How Large Software Fits Together

Start here

System design is how you plan a software system made of many parts so that it:

It is not “draw boxes for fun.” It is **decision-making under constraints**.

You should care because interviews, production incidents, and architecture reviews all use the same foundation vocabulary: clients, servers, data stores, caches, queues, load balancers, consistency, and trade-offs.

This is a map lesson. Later lessons go deep on each idea. Here you learn what the pieces are, why they exist, and which questions to ask first.

What you will learn

  1. Define system design in plain English.
  2. Name the main building blocks of internet backends.
  3. Separate functional requirements from non-functional ones.
  4. Estimate order-of-magnitude load (back-of-envelope).
  5. Walk a simple photo-sharing design without drowning in buzzwords.
  6. Recognize classic trade-offs you will meet everywhere.
  7. Know what “good enough” means for a first design.

What you should know first

You can start with everyday web use:

If you already know HTTP or databases, great—this lesson still sets shared language.

Words you need before we begin

TermPlain English
ClientThe app or browser acting for the user.
Server / serviceA program that accepts requests and does work.
Request / responseA question and answer over the network.
APIApplication Programming Interface — the agreed way to call a service.
DatabaseDurable storage for structured data.
CacheFast temporary storage of expensive results.
Load balancerSpreads traffic across healthy servers.
Message queueHolds work to be done later by workers.
LatencyHow long one operation takes.
ThroughputHow much work finishes per unit time.
AvailabilityHow often the system successfully serves users when needed.
ScalabilityAbility to handle more load by adding resources (well).
Fault toleranceKeep useful work going when some parts fail.
Trade-offA gain that costs something else (speed vs cost, consistency vs availability, and so on).

Simple story: a food court, not one giant kitchen

A single restaurant kitchen (one server + one database) can feed a neighborhood. A city food court adds:

Nobody builds a food court on day one for a home dinner. System design starts from **needs**, not from copying a city map.

The problem without intentional design

The ball of mud

One application does UI, payments, email, search, and admin tools. Any change risks everything. Scaling means buying a bigger single machine until you cannot.

Copy-paste microservices

Twenty tiny services, twenty deployment pipelines, no clear data ownership, every request fans out to twelve dependencies. Latency and incidents explode.

Ignoring non-functional needs

“It works on my laptop” with 10 users fails for 10,000. Design forces you to ask about load, failure, and data growth early.

Step-by-step explanation

Step 1 — Clarify what you are building

Write:

  1. Who uses it?
  2. What core actions do they take?
  3. What must never go wrong (money, safety, privacy)?
Example: photo sharing — upload photo, follow users, view feed.

Step 2 — Split functional vs non-functional requirements

Functional (what)Non-functional (how well)
Upload a photop95 upload API under 300ms metadata path
Show feedFeed available 99.9% of monthly window
Follow a userCorrect privacy: private accounts enforced

Interviews and production both punish designs that only list features.

Step 3 — Sketch the request path

Most internet systems share a skeleton:

Client → DNS → Load balancer → App servers → Database
                              ↘ Cache
                              ↘ Queue → Workers

You add pieces when a measured problem appears:

Step 4 — Do a back-of-envelope estimate

Rough numbers beat vibes.

Suppose:

Daily feed reads ≈ \(10^7 \times 5 = 5 \times 10^7\) feed loads. If each load hits the database for 20 rows naively, that is a billion row touches—probably too much. That estimate **justifies** caching or precomputed feeds.

You are not seeking perfect math. You are seeking whether you need fancy machinery.

Step 5 — Choose data storage deliberately

Questions:

One database is fine until requirements force specialization.

Step 6 — Plan for failure from day one (lightly)

Even a small design should answer:

You do not need multi-region active-active for a homework app. You do need to **name** failure.

Step 7 — State trade-offs out loud

Every solid design review includes sentences like:

If there are no trade-offs in your design, you have not looked.

Visual mental model

flowchart TB
  subgraph users [Users]
    Mobile[Mobile app]
    Web[Browser]
  end
  subgraph edge [Edge]
    DNS[DNS]
    LB[Load balancer]
  end
  subgraph core [Core services]
    API[API servers]
    Auth[Auth service]
  end
  subgraph data [Data plane]
    DB[(Primary database)]
    Cache[(Cache)]
    Obj[Object storage]
    Q[Queue]
    W[Workers]
  end
  Mobile --> DNS
  Web --> DNS
  DNS --> LB
  LB --> API
  API --> Auth
  API --> Cache
  API --> DB
  API --> Obj
  API --> Q
  Q --> W
  W --> DB

Learning question: Which box would you add first if the database CPU is hot on read-heavy feed traffic?

Caption: Start simple; add cache/queue/replicas when estimates or metrics demand them.

Complete worked example: tiny photo service v1

Starting situation

Build SnapMini:

Year-1 targets: 100k monthly users, not global viral scale.

Constraints

Decisions (v1)

ConcernChoiceWhy
App tierStateless API × 2 behind load balancerSurvive one instance death
MetadataPostgresUsers, follows, photo rows, transactions
BytesObject storage (S3-style)Cheap large files
FeedSQL query recent photos from follow set + short cacheVolume still small
EmailOut of scope / async laterNot core path
AuthManaged auth or simple session serviceDo not invent crypto

Execution path: upload

  1. Client requests upload URL or sends multipart to API.
  2. API authorizes user.
  3. Bytes land in object storage.
  4. API inserts photo metadata row.
  5. Returns photo id.

Failure behavior

Outcome

A boring design that can ship. Limitations: feed query may not survive 100× growth—document the scaling path (cache, fan-out on write) without building it yet.

How it works in production

Real companies encode foundations as:

Design is not a one-time diagram. It is a living agreement between product, eng, and ops.

Failure modes of “design process” itself

ModeSymptomFix
Premature scaleKafka + multi-region for 200 usersStart simpler; re-evaluate with metrics
No numbersEndless debateBack-of-envelope + prototypes
Hidden requirementsSecurity/privacy bolted on lateInclude non-functionals early
Single hero architectBus factor 1Shared design reviews
Diagram worshipPretty boxes, unclear APIsDefine interfaces and data ownership

Trade-offs you will reuse

TensionClassic directions
Consistency vs availability/latencyStrong reads vs faster stale reads
Cost vs headroomOver-provision vs scale-to-zero risk
Simplicity vs isolationMonolith vs many services
Build vs buyManaged DB vs self-run
Sync vs asyncImmediate correctness vs decoupling

Compare with related concepts

LessonRole after this foundation
Latency, throughput, bandwidthQuantify performance
Availability / reliability / fault toleranceQuantify and design for failure
Load balancing / caching / queuesConcrete building blocks
CAP / consistency modelsData correctness under distribution

Common misunderstandings

  1. “System design = microservices.”
Microservices are one style. Many excellent systems are modular monoliths.
  1. “More boxes means better design.”
Complexity is a cost. Earn each box.
  1. “If it passes the interview, it is production-ready.”
Interviews test structured thinking. Production adds org, cost, compliance, and legacy.
  1. “Non-functional requirements are optional polish.”
They are often the difference between a demo and a product.
  1. “We can add security later.”
Authn/z and data protection shape APIs and storage from day one.

Check your understanding

  1. What is system design in one sentence?
  2. Give two functional and two non-functional requirements for a ride-sharing app.
  3. Why estimate load before adding a cache?
  4. Name three building blocks in a typical web backend path.
  5. State one trade-off in the SnapMini v1 design.

Practice

  1. Write requirements for a URL shortener (functional + non-functional).
  2. Back-of-envelope: 1M new URLs/day, 100M redirects/day—what is stressed more, write path or read path?
  3. Draw a v1 design with ≤6 component types.
  4. List three failures and how v1 behaves.
  5. Propose what you would change at 100× traffic—and what you would not change yet.

Revision summary

Glossary

TermDefinition
System designPlanning components and interactions to meet requirements.
Non-functional requirementQuality attribute such as latency, availability, security.
Stateless serviceInstance that does not keep must-have session memory locally.
Back-of-envelope estimateRough capacity math to guide design.

Abbreviations and terminology

What to learn next

  1. Latency vs throughput
  2. Availability
  3. Scalability
  4. Fault tolerance
  5. Load balancing
  6. Caching 101
  7. Message queues

FAQ from first-time learners

Q: How detailed should a first diagram be?
A: Enough to show request flow, data stores, and failure points—not every class name.

Q: Do I need Kubernetes to design systems?
A: No. Learn concepts first. Orchestration is an implementation choice.

Q: Where do interviews stop and real jobs start?
A: Interviews reward clear requirements, estimates, and trade-offs. Jobs add stakeholders, migrations, and multi-year evolution.

Track: Distributed Systems

Next: CAP Theorem — Consistency, Availability, and Partition Tolerance

By Shubham Jain

All articles · Study paths

Shubham Jain · Learning Lab