ayushsalampuriya.xyz Revise

System Design · Core

Scaling Fundamentals

Walk a product from one box to millions of users: when to split tiers, add cache, load-balance, replicate, and push static traffic to the edge.

1. Why stages matter in interviews

Interviewers rarely want you to jump straight to Kafka and fifty microservices. They want a growth story: start simple, name the bottleneck, then add the next component. Memorize the six-stage ladder below and narrate it with a concrete product (photo app, marketplace, SaaS API).

2. Stage 1 — Single server

[ Users ] | v [ One machine: DNS + Web/App + DB + files ]

Everything shares one CPU, RAM, disk, and network NIC. Fine for demos and early MVPs. Typical failure modes: disk fills with uploads, DB locks under concurrent writes, or a deploy takes the whole product offline.

3. Stage 2 — Separate database

[ App / Web tier ] ----SQL----> [ Dedicated DB host ] | | static files data + indexes

Web work is often CPU/memory bound; databases are I/O and lock bound. Splitting tiers lets you size and restart them independently. Put the DB on faster disks, tune connection limits, and keep pools on the app side.

4. Stage 3 — Cache

Request --> App --> Cache hit? --yes--> return \ miss --> DB --> populate cache --> return

Cache hot, mostly-read objects (profiles, product pages, session blobs) where a few seconds of staleness is acceptable. Prefer cache-aside first; document TTL and invalidation on writes. Full deep dive: Caching.

Cache patterns (quick recap)

Cache locations

Browser / client → CDN edge → App local (L1) → Redis/Memcached → DB buffer pool Interview: draw CDN + distributed cache at minimum

5. Stage 4 — Multiple web servers + load balancer

Client --> LB --> App1 --> App2 --> App3 --> Cache / DB

Horizontal scale of the compute tier. Health checks remove dead nodes. Critical rule: keep apps stateless. Sticky sessions hide bad design and break when a node dies. Store sessions in Redis or signed tokens so any instance can serve any user.

6. Stage 5 — Database replication

Writes --------------> Primary | async/sync ship Reads --> Replica A <---+ --> Replica B <---+

Replicas multiply read QPS and give you a failover candidate. Trade-off: replica lag means a user may not see their own write if you read from a replica immediately. Mitigations: read-your-writes via primary for a short window, or route post-write reads to primary.

7. Stage 6 — CDN

User --> nearest Edge PoP --hit--> asset \ miss --> Origin (object store / app) --> fill edge

Images, JS, CSS, video segments, and downloads leave your origin. Lower latency for global users and fewer origin bytes. Pair with good Cache-Control and a purge story for broken assets.

8. Vertical vs horizontal scaling

AxisVertical (scale up)Horizontal (scale out)
ActionBigger CPU/RAM/disk on one nodeMore nodes behind a balancer
ProsSimple ops, no shardingNear-linear capacity, better fault isolation
ConsHard ceiling, still a SPOFDistributed complexity, data partitioning
Typical useEarly DB growth, stateful enginesStateless web, cache clusters, shardable stores

In practice you do both: vertically size each role to a sweet spot, then scale out when one machine cannot hold the write rate or dataset.

9. Sharding strategies

Replicas help reads. Sharding helps when writes or data size exceed one primary.

StrategyIdeaWatch out
Rangeuser_id 1–1M on shard AHot ranges (new IDs, popular prefixes)
Hashhash(key) % NRebalancing when N changes; prefer consistent hashing
DirectoryLookup maps key to shardLookup becomes critical path / SPOF
Geo / tenantShard by region or customerUneven tenants; cross-tenant analytics hard

10. Stateless application tier

Bad: App2 holds in-memory cart for user U LB sticky → U always hits App2 (until App2 dies) Good: Cart in Redis / DB; JWT or session id only on client Any AppN can serve U after LB health check
  1. No local disk as source of truth for user state.
  2. Uploads go to object storage, not the app box.
  3. Feature flags and config from a central store.
  4. Idempotent handlers so retries after failover are safe.

11. Sixty-second interview pitch

Start monolith on one box. Split DB. Cache hot reads. Add LB and stateless apps. Replicate DB for read scale and HA. CDN for static. Shard only when the primary cannot absorb writes or storage. Every step names a bottleneck and a trade-off.

12. Reference latency numbers

OperationBallpark
L1/L2 cache reference~0.5–7 ns
Main memory reference~100 ns
SSD random read~16–150 μs
Same-datacenter RTT~0.5 ms
Redis GET same AZ~0.2–1 ms
Disk seek (HDD)~10 ms
Cross-region RTT~50–150 ms
Read 1 MB sequentially from network~10 ms (order-of-magnitude)

Memorize orders of magnitude, not exact nanos. Use them to justify cache, CDN, and “why not sync cross-region on every click.”

13. Reference throughput numbers

ResourceRough capacity (order of magnitude)
1 Gbps NIC~125 MB/s theoretical
Commodity web instancehundreds–thousands QPS simple JSON (varies wildly)
Postgres primary (well-tuned)thousands of simple writes/s before sharding talk
Redis instance100k+ simple ops/s common ballpark
Kafka partitiontens of MB/s sequential; scale via partitions

Always re-estimate for the problem’s payload size. See also Estimation.

Quick revision

  • Six stages: single box → split DB → cache → LB+multi-app → replicas → CDN.
  • Cache-aside / through / behind — know the one-liner for each.
  • Cache locations: client → CDN → L1 → Redis → DB.
  • Vertical = bigger machine; horizontal = more machines; apps stay stateless.
  • Replicas scale reads; sharding scales writes and data size.
  • Memorize latency/throughput orders of magnitude for trade-off talk.
  • Always narrate bottleneck → next component → trade-off.