Back to System design

System Design Trade-offs Cheat Sheet

easy
All
FrameworkTrade-offs

Trade-offs are the substance of system design. There is no universal best architecture; only the best fit for a set of constraints. Internalize the dimensions so you can articulate the choice for any system.

Key Concepts

1
1. Consistency. Strong (linearizable) — required for source-of-truth (money, inventory, locks). Cost: latency + availability. Eventual — high availability + scale (feeds, like counts). Cost: stale reads. Causal / Read-your-writes — middle ground; client sees its own writes. Default: strong for primary data, eventual for derived/cached. Tunable stores (Cassandra, DynamoDB) let you mix.
1. Consistency.
2
2. Latency / durability / throughput. Sync replication: durable, slow tail. Async: fast, can lose writes on failover. Sync write to cache + DB: consistent, double write cost. Write-back cache: fastest, may lose on crash. Group commit: amortize fsync over many writes.
2. Latency / durability / throughput.
3
3. Sharding / scaling. Vertical: simplest until ceiling (~64-128 cores). Read replicas: scale reads, lag risk. Functional split (microservices): independent scale + deploy; org and network complexity. Horizontal shard: scales writes; cross-shard pain. Multi-region: latency + DR; conflicts + cost. Shard key trade-offs: user_id (even, no range), tenant (isolation, mega-tenant risk), time (range fast, hot tail).
3. Sharding / scaling.
4
4. Async / sync boundaries. Sync RPC: simple, tight coupling, fragile to slowness. Async queue: decouples, backpressure, retry; eventual consistency. Event log (Kafka): replayable, multi-consumer; harder ordering. Default: sync inside request/response; async for everything else.
4. Async / sync boundaries.
5
5. Storage type + build/buy. Object store (S3): big blobs, immutable. KV: single-key at scale. Document: hierarchical, flexible schema. Wide-column: high write rate, time-series. Relational: joins, transactions. Build vs buy: managed until usage justifies ops investment. Revisit at $10M+/yr cloud spend or when differentiation requires custom internals. Microservices vs monolith: well-structured monolith until 50+ engineers; microservices solve org scaling as much as technical.
5. Storage type + build/buy.

Consistency

Strong: correctness paramount (money, inventory, lock state). Cost: latency + availability.

Eventual: high availability + scale (social, catalog). Cost: stale reads.

Causal / Read-your-writes: pragmatic middle; client sees its own writes.

Default: strong for source-of-truth tables, eventual for derived/cached views.

Tunable: Cassandra (per-query), DynamoDB (strong vs eventual reads).

Latency / Durability / Throughput

Sync replication: durable, slow tail.
Async replication: fast, can lose writes on failover.
In-memory only: fastest, lost on restart.
Write-through cache: consistent, doubles write cost.
Write-back cache: fastest writes, may lose on crash.
Group commit: amortize fsync over many writes.

Sharding / Scaling

Vertical scale: simplest until ceiling.
Read replicas: scale reads, lag risk.
Functional split: microservices; org and tech complexity.
Horizontal shard: scales writes; cross-shard pain.
Multi-region: latency + DR; conflict + cost.

Shard key trade-offs:
- User-id: even load, no range scans.
- Tenant-id: easy isolation, mega-tenant risk.
- Time-based: range queries fast, hot tail.

Async / Sync

Sync RPC: simple, tight coupling, fragile to slowness.
Async queue: decouples, backpressure, retry; eventual consistency.
Event log: replayable, multi-consumer; harder ordering.

Default: sync inside a request/response; async for everything else.

Storage Type

Object store (S3): big blobs, infrequent change, cheap, immutable.
Block (EBS): VMs, databases.
File (EFS): legacy POSIX needs.
KV (DynamoDB): single-key access, scale.
Document (MongoDB): hierarchical, flexible schema.
Wide-column (Cassandra): high write rate, time-series.
Relational: joins, transactions, ad-hoc queries.

Build vs Buy vs Open-source

Buy/managed: faster to ship, lock-in, cost at scale.
Open-source: flexible, ops burden, hiring cost.
Build: only when neither fits and it's a core differentiator.

Default: managed until usage justifies ops investment.

Revisit decision when:
- Cloud bill > $10M/yr → consider self-hosted.
- Hiring 10+ infra engineers → open-source becomes viable.
- Differentiation requires custom internals → build.

Microservices vs Monolith

Monolith: deploy together, fewer moving parts, fast iteration up to a point.
Microservices: independent deploy + scale, polyglot tech, network complexity.

Default: well-structured monolith until 50+ engineers; modularize first, split when boundaries are clear.

Microservices solve organizational scaling (small teams own services) as much as technical scaling.