system-design/common-tradeoffs.md

47. Cheat Sheet: Common Trade-offs & Patterns

Quick reference. The interviewer rewards reasoning about trade-offs; this distills the recurring ones.

~6 min read·updated 5/29/2026

47. Cheat Sheet: Common Trade-offs & Patterns

Quick reference. The interviewer rewards reasoning about trade-offs; this distills the recurring ones.

47.1 Database choice

WorkloadPickWhy
OLTP, relational, < 10 TBPostgres / MySQLACID, joins, mature
OLTP, distributed-relationalSpanner, CockroachDBglobal ACID
OLTP, KV at scaleDynamoDB, Cassandrainfinite horizontal scale
Document / flexible schemaPostgres JSONB > MongoDBone DB to operate
Wide-column / time-seriesCassandra, Bigtableappend-mostly, sparse
CacheRedisrich types, fast
SearchElasticsearchinverted index + facets
Vector / embeddingpgvector / PineconeANN
GraphNeo4jonly when graph-deep
AnalyticsBigQuery / Snowflake / ClickHousecolumnar, MPP
Object blobsS3 / GCScheap, scalable

Default: Postgres + Redis + S3 covers most early-stage products.

47.2 Consistency vs latency vs availability

  • Strong consistency: linearizable. Slow (consensus). Use for: money, locks, leader, sessions.
  • Eventual: cheap, fast. Use for: counters, feeds, search results, analytics.
  • Per-operation choice: writes via consensus, reads from cache.

PACELC framing:

  • Partition: trade A vs C.
  • Else: trade L vs C.

47.3 Push vs pull

PropertyPush (write fan-out)Pull (read fan-out)
Read latencyFastSlow
Write costHighLow
Stale dataPossibleAlways fresh
Best forRead-heavy, fixed audienceMany followers, low read

Hybrid (Twitter): push for ordinary; pull for celebrities.

47.4 SQL vs NoSQL

  • SQL when: relational integrity, joins, transactions, ad-hoc queries, < 100 TB.
  • NoSQL when: massive scale (100 TB+), simple access patterns, write-heavy, schema flexibility (with care).

Modern distributed SQL collapses many "must use NoSQL" cases.

47.5 Sync vs async

  • Sync (REST/gRPC) when: caller needs the result, low latency, simple flow.
  • Async (queue/event) when: long-running, decoupled, fan-out, retry-friendly.

A heavy async pipeline for a simple sync need is over-engineered. The reverse is also a bug.

47.6 Monolith vs microservices

  • Monolith when: < 30 engineers, single product, tight transactions.
  • Microservices when: many teams, independent deploys, divergent scale needs, polyglot needs.

Modular monolith is the pragmatic stepping stone.

47.7 Caching strategies

  • Cache-aside: app manages. Default.
  • Write-through: writes to both. Simpler; slow writes.
  • Write-behind: write to cache, async DB. Risk of loss.
  • Read-through: cache library fetches. Cleaner code, less control.
  • Refresh-ahead: proactive refresh. Avoids miss spike.

For invalidation: TTL + explicit invalidation + versioning. Pick based on freshness needs.

47.8 Replication

  • Single-leader: simple, predictable. Default.
  • Multi-leader: high write availability, conflict resolution required.
  • Leaderless (Dynamo): tunable consistency, write any node, read repair.

Sync ack vs async: sync = no data loss, slow under follower issues; async = fast, possible data loss on failover.

47.9 Partitioning

  • Hash: uniform load, no range queries.
  • Range: range queries, hot partition risk.
  • Hybrid: hash prefix + sort key (Cassandra clustering).
  • Geo: locality, multi-region.

Choose partition key for: balanced load + access pattern affinity + stability.

47.10 Index choice

NeedIndex
Equality / range on one columnB-tree
Multi-column equality / rangeComposite B-tree
Avoid table fetchCovering index
Filter on subsetPartial index
Full-textGIN trigram or Elasticsearch
JSONBGIN
GeoGiST + PostGIS, or H3 / S2

47.11 Queue choice

  • Kafka: huge throughput, log retention, replay.
  • RabbitMQ: complex routing, lower throughput.
  • SQS: managed AWS, simple.
  • Redis Streams: in-stack, low-volume.

Default to Kafka unless you specifically need RabbitMQ's routing or SQS's managed simplicity.

47.12 Event delivery

  • At-most-once: send and forget.
  • At-least-once + idempotent consumer = effectively once. The production pattern.
  • "Exactly-once delivery" is a marketing term.

Outbox pattern always.

47.13 Real-time push

  • Polling: simple, wasteful.
  • Long polling: better, still HTTP.
  • SSE: server → client, simple.
  • WebSocket: bidirectional, complex.
  • gRPC streams: internal use.

For chat: WS. For dashboards: SSE. For mobile push: APNS/FCM.

47.14 Auth model

  • API key: server-to-server, simple.
  • JWT (short-lived) + refresh: web/mobile sessions.
  • OAuth 2.0 + OIDC: third-party / SSO.
  • mTLS: zero-trust internal.
  • Session cookie: classical web.

For new web app: short-lived JWT + refresh + HTTP-only Secure cookies.

47.15 Hot key mitigations

  • Replicate hot key to multiple shards.
  • Local in-process cache for top-N.
  • CDN-cache the response.
  • Rate limit aggressors.
  • Compute approximate (Count-Min) instead of exact.

47.16 Counters at scale

  • Don't INCR a Postgres row at 100K/sec.
  • Stream events → aggregate → materialized counter.
  • Sharded counters (N counters per logical key, sum on read).
  • HyperLogLog for unique counts.
  • Redis sorted sets for leaderboards.

47.17 Geographic / multi-region

PatternWhen
Single-regionMost early-stage
Active-passive (DR)RTO minutes-hours
Active-active readsRead locality, single-region writes
Active-active multi-masterHighest availability; conflict resolution required
Distributed SQL (Spanner)Strong consistency globally

For most: single-region + DR plan.

47.18 ID generation

  • UUID v4: random, no order.
  • UUID v7 / ULID / KSUID: time-prefixed; sortable.
  • Snowflake: 64-bit, time-prefixed, machine-id, sequence.
  • DB autoincrement: simple, single-DB only.
  • KGS: pre-allocated pools per app server.

For sharded systems: time-prefixed (Snowflake, ULID) so primary key doesn't fragment indexes.

47.19 File / blob storage

  • < 1 MB and frequently accessed: maybe DB.
  • 1 MB or large catalog: object storage (S3) + CDN.

  • Chunk + content-address (Dropbox-style) for dedup + sync.

Never store images in your DB.

47.20 Search

  • Full-text small data: Postgres + GIN trigram.
  • Full-text + facets: Elasticsearch.
  • Massive scale + ranking: Vespa.
  • Vector / semantic: pgvector / Pinecone / Weaviate.
  • Hybrid (lexical + vector): preferred for modern search UX.

47.21 Failure handling primitives

  • Retry with exponential backoff + jitter.
  • Circuit breaker: fail fast when downstream broken.
  • Bulkhead: isolate connection pools.
  • Timeout: every external call.
  • Idempotency keys: every external write.
  • Outbox: DB write + event atomically.
  • DLQ: poison messages.
  • Health checks + draining: zero-downtime ops.
  • Hedging: dup request to two replicas; first wins.

47.22 Cost levers (prod)

  • CDN bandwidth: ~10× cheaper than direct.
  • Cache hit ratio: directly cuts DB load and storage IOPS.
  • Right-sizing: monitor actual; don't over-provision.
  • Spot / preemptible: 60-80% cheaper for stateless workloads.
  • Tiered storage: hot (SSD) + cold (S3 IA / Glacier).
  • Compression: bandwidth + storage; choose Zstd / Brotli.
  • Reserved / committed use: 30-50% off for steady workloads.

47.23 What "scaling" means concretely

BottleneckMitigation
CPU on appMore instances (stateless)
DB read loadRead replicas; cache
DB write loadSharding; queue + batch
Network bandwidthCDN; compression
StorageObject storage; tiered
Hot keyReplicate; local cache
Tail latencyHedging; cache; warm pools
Cross-region latencyMulti-region; edge compute

47.24 Things to mention to score points

  • Observability: metrics + tracing + logging.
  • SLOs / error budgets.
  • Idempotency keys.
  • Backpressure.
  • Circuit breakers.
  • Failure isolation (per-tenant, per-shard).
  • Backups (with tested restores).
  • Security: TLS, mTLS, KMS, secrets, OWASP.
  • Compliance if domain-relevant: GDPR, PCI, HIPAA.

47.25 Things NOT to over-mention

  • Microservices everywhere.
  • Kubernetes for everything.
  • Specific cloud product names ("we'd use AWS DocumentDB"). Talk patterns; mention products as instances.
  • New shiny tech without justification.
  • Re-implementing existing primitives unless asked.

Key takeaways

  • Trade-offs > tools. Pick a thing because of what it gives up, not because it's hot.
  • Keep a mental matrix: workload → store → consistency → scale lever.
  • Defaults (Postgres + Redis + S3, push fan-out, JWT + refresh) cover most.
  • Show you know the failure modes and the operational cost, not just the happy path.

// 0 views

main
UTF-8·typescript