You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Key system design building blocks and trade-offs, grouped by subtopic. For CAP, consistency, replication, and sharding internals, see distributed.md; for API design, idempotency, and outbox, see backend.md; for auth and web security, see security.md.
Interview framework
Structure and estimates
Order: requirements (functional + scale, latency, availability, consistency) → estimates → API → data model → high-level design → deep dive on the hardest 1–2 parts → bottlenecks and trade-offs.
Jitter TTLs so keys written together don't expire together.
Cache and database consistency
On write, delete the key rather than updating it, so concurrent writers can't leave an older value in place.
Cache-aside still races: a slow reader can refill the cache with a value read before the write — bound it with a TTL, a delayed second delete, or leases (Facebook memcache).
For many writers, invalidate from the database's change stream (CDC) instead of from application code.
An inverted index maps each term to the documents containing it; relevance scoring is usually BM25.
Elasticsearch/OpenSearch are near-real-time (new docs searchable after a refresh, ~1 s default), and the primary shard count is fixed at index creation — resize by reindexing or split/shrink.
OLAP stores use column storage, compression, and vectorized scans of few columns over many rows, with star schemas (facts + dimensions).
Treat search indexes and warehouses as derived stores, fed by CDC from the source of truth.
Enforce at the gateway, keyed by user, API key, or IP; reject with 429 and Retry-After.
Share counters in Redis so every server sees one limit; wrap INCR + EXPIRE in MULTI or a Lua script, or a crash between them leaves a counter with no TTL.
A local per-instance limiter skips the round trip but is only approximate (limit ÷ instances).
Reliability and operations
Availability math
Components in series multiply: 99.9% × 99.9% ≈ 99.8%.
Redundant components in parallel fail only together: 1 − 0.001² ≈ 99.9999%.
Both formulas assume independent failures; a shared zone or dependency wipes out most of the parallel redundancy gain.
Multi-region and disaster recovery
RPO = acceptable data loss, RTO = acceptable recovery time; together they pick the tier.
Async cross-region replication means RPO > 0; active-active also needs conflict handling or a home region per record, plus global routing (GeoDNS, anycast).
A failover that was never rehearsed rarely works: run regular game days.
SLIs, SLOs, error budgets
SLI = what's measured, SLO = internal target, SLA = contractual promise (looser than the SLO).
The gap to 100% is the error budget — spend it on releases, slow down when it's exhausted.
Alert on SLO burn rate and user-felt symptoms, not on every cause (CPU at 80%).
Observability
Metrics: numeric time series (Prometheus); golden signals latency, traffic, errors, saturation — RED for services, USE for resources.
Logs: structured, centralized, tagged with a request ID. Traces: a request's span tree across services (OpenTelemetry).
Metrics say something is wrong, traces say where, logs say why.
Percentiles can't be averaged across hosts or time windows: merge the histograms (or sketches), then take p99.
High-cardinality labels (user ID, request ID) multiply Prometheus time series; keep them in logs and traces.
Architecture
Monolith vs microservices
Default to a modular monolith: in-process calls and local transactions, with module boundaries that could later become services.
Extract a service for a concrete reason (independent scaling, deploy cadence, team ownership); boundaries mirror teams (Conway's law).
Service discovery
Instances register with a registry (Consul, etcd, Eureka) and drop out on failed health checks; clients or a load balancer resolve names to healthy instances.
Geohash encodes lat/lon as a string: a shared prefix means nearby, but close points can straddle a cell boundary and share none.
Pick a precision whose cell is at least the search radius, then query the cell and its 8 neighbors.
A quadtree subdivides dense areas further, adapting to uneven density; Google S2 and Uber H3 use hierarchical cells the same way.
Classic designs: user-facing
URL shortener
Read-heavy (~100:1); base62 in 7 characters gives ~3.5 trillion keys.
Keys from hash + collision check, a counter encoded in base62 (predictable unless shuffled), or a pre-generated key pool.
301 is cached by browsers by default (less load, lost clicks); 302 isn't cached without explicit freshness headers, so every click hits you (analytics). Collect analytics asynchronously.
News feed
Fan-out on write: precompute followers' feeds at post time — instant reads, but a celebrity triggers massive write amplification.
Fan-out on read: merge followees' posts at read time — slower reads, no amplification.
Hybrid: push for normal accounts, pull for celebrities; store post IDs, hydrate from cache, rank as a separate step.
Chat system
A persistent WebSocket per client; a connection registry (user → server) routes messages via pub/sub.
A server-assigned per-conversation sequence number orders messages; a client-generated message ID dedupes retries.
Offline users get a push notification and fetch on reconnect; large groups hit the same fan-out problem as feeds.
Typeahead
A trie (or prefix index) with precomputed top-k suggestions per node, built offline from query logs and cached aggressively.