Intro to System Design7 min · 3 of 64

Why system design matters

Turn scalability, availability and speed into numbers you can defend: QPS ceilings, availability budgets, and a latency ladder that kills bad plans early.

A feature either works or it does not, and you find out in an afternoon. Whether a system survives ten times its current traffic, a lost database node, or a dependency that slows from 20 ms to 200 ms is decided months earlier, by design choices that are expensive to reverse. System design is the work of fixing those non-functional properties on purpose rather than discovering them in production.

Six properties carry most of the weight. Each has an arithmetic form, and that is what separates a design answer from an opinion.

Scalability

Scalability is the ability of a system to handle a growing amount of work, either by adding resources to an existing machine (vertical scaling) or by adding more machines (horizontal scaling). A well-designed system absorbs growth without a re-architecture.

Put the social media example in numbers. Assume 1 million daily active users at 20 requests each:

1,000,000 DAU x 20 req/day = 20,000,000 req/day
20,000,000 / 86,400 s      = ~230 QPS average
peak is typically 2-5x     = ~1,000 QPS peak

A single commodity Postgres box handles roughly 5,000 simple queries per second, so today the whole product fits on one machine with room to spare. Now apply the 10x growth the product team is forecasting: 2,300 QPS average and around 10,000 QPS peak. That is twice the ceiling of a single box, and tuning does not close a 2x gap in a year.

The design response is ordered by cost, not by sophistication: add a cache to remove the repeated reads first, then read replicas, and only then shard. A system built for one box and grown to ten thousand QPS by accident goes slow, then unresponsive, then down.

Reliability and availability

Reliability is the probability that a system functions correctly over a period: it produces the right output and does not fail often. Availability is the proportion of time the system is operational and reachable. They are not the same property, and a system that is down frequently is useless even if it is perfectly correct while it is up.

Availability is a budget, in minutes:

30 days x 24 h x 60 min = 43,200 min/month
99.9%  -> 0.1%  of that = ~43 min/month down
99.99% -> 0.01% of that = ~4.3 min/month down

Availability also multiplies along a request path. A service that is itself 99.99% available but calls four dependencies at 99.9% each, all on the critical path, delivers 0.9999 x 0.999^4 ≈ 0.9959 — about 177 minutes of user-visible downtime per month, roughly forty times its own failure budget. Every synchronous dependency you add spends availability. That is the argument for making a call asynchronous, for a cached fallback, and for a circuit breaker that fails fast instead of holding threads open.

Availability is bought with redundancy: load balancing across interchangeable servers, automatic failover, and geographic distribution.

Each box that can die has a named survivor. The read replica is 10–100 ms behind, which is fine until it is promoted — then the last writes are gone.
A topology that survives a dead app server and a lost database leadermissreplicatesleader lost: promoteClientLoad balancerdrops dead nodesApp server 1App server 2CachePostgresleaderRead replicaasync, 10–100 msbehind

Scroll to zoom · drag to pan · 0 fits · Esc closes

Read the dotted edges: those are the paths taken when something has already gone wrong. The replica earns its keep twice — it absorbs read traffic normally and it is the failover target when the leader is lost. The cost sits on the replication edge: replication is asynchronous, so a user who writes to the leader and then reads from a replica can see their own update missing for the length of the lag. Read-your-writes has to be handled explicitly, not assumed.

Fault tolerance

No system is perfect and components will fail. Fault tolerance is the ability to keep operating correctly while they do: backup capacity, automatic failover, and isolation so one failing part does not take the rest with it. At real scale this stops being hypothetical. A fleet of 1,000 machines with a 2% annual failure rate loses one roughly every 18 days, so "a node is down right now" is the normal state, not the incident.

Performance

Scalability is about handling more work. Performance is how fast the system is at a given load, and it is measured at percentiles, not averages: p99 is what users feel, and the mean hides the tail entirely.

Performance claims live or die against the latency ladder. A main memory reference is 100 ns; an SSD random read is 100 µs; a round trip inside one datacenter is 0.5 ms; a spinning disk seek is 10 ms; a round trip from India to US East is about 200 ms. That last number ends arguments. If your p99 budget is 200 ms and your users are in India while your only region is US East, the network alone consumes the entire budget before a single byte is processed. No query tuning recovers it — you either serve from a region near the user or push cacheable responses to a CDN edge.

The ladder also explains capacity. By Little's Law, concurrency = arrival rate x latency, so 500 QPS at 200 ms means 100 requests in flight at once. If a dependency degrades from 20 ms to 200 ms, in-flight work jumps from 10 to 100 and a connection pool sized at 50 is exhausted. The service is not "slow"; it is queueing, and to users it reads as an outage.

Maintainability

Maintainability is the ease with which a system can be modified, updated, and fixed. A well-designed system is modular, documented, and understandable, which lowers the cost of every future change. Poorly designed systems become legacy code quickly. This property has no clean formula, which is exactly why it is the first one traded away and the one that costs the most to recover.

System design is the foundation under a large system: the difference between one that absorbs a growing user base and one that collapses under its own weight. It sets the user experience, the operating cost, and how long the team can keep shipping.

In an interview

For a senior interview, a working command of these properties is most of the signal. The interviewer is not testing whether you can define availability — they are testing whether you turn a vague requirement into a number and let that number choose the design.

What to say: state the property, quantify it, then name the mechanism. "Twenty million requests a day is about 230 QPS average and roughly 1,000 at peak. One Postgres box handles about 5,000 simple QPS, so we do not shard yet — I would add a cache and a read replica and revisit at 10x." Two sentences, and they show scalability, capacity estimation, and restraint at once.

The specific mistake that loses points is listing the properties as virtues — saying the design is scalable, available, and fault tolerant without ever choosing between them. These properties compete. Synchronous replication buys consistency and spends latency; more nines cost more machines and more operational load. An answer that claims all of them at no cost tells the interviewer you have not built one. Name the trade you are making and the number that justifies it, and check your figures against the requirements you gathered rather than inventing a target mid-answer.

Check yourself

1. Your service runs at 1M DAU and 20 requests per user per day on a single Postgres box. Product forecasts 10x users in a year. Do you shard now?

No. Today: 20M requests/day ÷ 86,400 ≈ 230 QPS average, ~1,000 QPS peak, against a ~5,000 QPS box — comfortable. At 10x: ~2,300 average and ~10,000 peak, which is twice the ceiling. Sharding is the expensive last move: cache first, then read replicas, and shard when replicas stop covering the write path. Committing to shards a year early buys a rewrite you did not need.

2. Your API is 99.99% available in isolation but calls four services on the critical path, each at 99.9%. What do users experience, and what do you change?

0.9999 x 0.999^4 ≈ 0.9959, which is about 177 minutes of downtime per month rather than the 4.3 minutes your own service promises. The count of synchronous dependencies is the availability budget. Move whichever calls are not needed for the response off the critical path, and give the rest timeouts with a cached or degraded fallback so one dependency cannot take the whole request down.

3. You are given a 200 ms p99 budget for users in India. All servers are in US East. Can tuning the database get you there?

No. The India to US East round trip alone is about 200 ms, so the budget is spent before any work begins, and shaving a 30 ms query changes nothing. The only answers are physical: serve from a region near the user, or put cacheable responses at a CDN edge so that only uncacheable writes pay the crossing.