vladvitan.com

System Design Cheatsheet


← back to notes

When estimating the capacity of a system, think about:

  • Traffic
  • Latency
  • Storage
  • Memory
  • Bandwidth
  • Resources
  • Costs

Useful Heuristics

  • Writes are more expensive than reads — design for read-heavy workloads when possible
  • Compression saves bandwidth — typical text compression: 3–10× reduction
  • Max ~2,000 RTT/s within a datacenter — plan for batching if you need more
  • Max ~7 RTT/s cross-region — minimize cross-region calls in hot paths
  • Memory is ~100× faster than SSD, SSD is ~100× faster than HDD
  • Network latency is dominated by distance — speed of light = ~3.3 µs per km (in fiber)
  • Protobuf is ~3× smaller than JSON — consider for high-throughput APIs
  • S3 is slow for small objects — batch or use a cache layer
  • Redis can handle 100K+ ops/s — often the first caching choice
  • Database connection overhead is ~1-5ms — use connection pooling
  • CDN reduces latency by 10× — for static content, always use a CDN

Latency Numbers

OperationLatencyNotes
L1 cache reference0.5 ns~4 cycles
Branch mispredict3 ns~10-15 cycles
L2 cache reference4 ns~12 cycles
L3 cache reference10 ns~40 cycles
Mutex lock/unlock (uncontended)17 ns
Main memory reference100 ns100× slower than L1
Compress 1 KB (Snappy/Zippy)10 µs
Read 4 KB randomly from NVMe SSD5 µs~200K IOPS
Read 1 MB sequentially from memory25 µsDDR5 ~50 GB/s
Read 1 MB sequentially from NVMe SSD150 µs~7 GB/s (Gen4/5)
Datacenter RTT (same zone)500 µs~2,000 RTT/s possible
Read 1 MB from 1 Gbps network10 ms1 Gbps = 125 MB/s
HDD seek10 ms
Read 1 MB sequentially from HDD30 ms~30 MB/s
Cross-region datacenter RTT50–150 ms~7 RTT/s worldwide
Round trip CA ↔ Netherlands150 msSpeed of light limit

Key formulas:

Total latency (serial operations):
Total = Latency₁ + Latency₂ + Latency₃ + ...

Total latency (parallel operations):
Total = max(Latency₁, Latency₂, Latency₃, ...)

Network latency estimation:
Min RTT ≈ Distance (km) × 2 ÷ 200,000 km/s (speed of light in fiber)
Example: NYC to London (5,500 km) = 5,500 × 2 ÷ 200,000 = 55 ms minimum

Percentile latencies (rule of thumb):
p50 ≈ median latency
p99 ≈ 2-10× p50 (depends on system)
p99.9 ≈ 2-5× p99

Latency budget allocation:
If target p99 = 200ms, allocate:
- Network: 20-30%
- Application: 30-40%
- Database: 30-40%
- Buffer: 10-20%

Availability & Downtime

AvailabilityDowntime/YearDowntime/MonthDowntime/Week
90% (1 nine)36.5 days3 days16.8 hours
95%18.25 days1.5 days8.4 hours
99% (2 nines)3.65 days7.3 hours1.7 hours
99.9% (3 nines)8.76 hours43.8 minutes10 minutes
99.99% (4 nines)52.6 minutes4.4 minutes1 minute
99.999% (5 nines)5.26 minutes26 seconds6 seconds
99.9999% (6 nines)31.5 seconds2.6 seconds0.6 seconds

Key formulas:

Downtime = (1 - Availability) × Time Period

Downtime/year  = (1 - availability) × 365 × 24 × 60 minutes
Downtime/month = (1 - availability) × 30 × 24 × 60 minutes
Downtime/week  = (1 - availability) × 7 × 24 × 60 minutes

Combined availability (serial):   A_total = A₁ × A₂ × A₃ × ...
Combined availability (parallel): A_total = 1 - (1 - A₁) × (1 - A₂) × ...

Example (serial): Two services at 99.9% each → 0.999 × 0.999 = 99.8%
Example (parallel): Two services at 99% each → 1 - (0.01 × 0.01) = 99.99%

Traffic Estimation (Requests ↔ RPS)

Key formulas:

  • 1 month ≈ 2.5 million seconds
  • 1 day ≈ 86,400 seconds ≈ 100K seconds
Requests/MonthRequests/DayRequests/Second (RPS)
1 million33K~0.4
2.5 million83K~1
10 million333K~4
100 million3.3M~40
1 billion33M~400
10 billion333M~4,000
100 billion3.3B~40,000

Quick conversion:

  • Monthly → Daily: divide by 30
  • Daily → RPS: divide by 100K (or 86,400)
  • Monthly → RPS: divide by 2.5M

Network & Bandwidth

ContextTypical Bandwidth
Within datacenter10–100 Gbps
Between datacenters10 Mbps – 1 Gbps
Home internet100 Mbps – 1 Gbps

Bits vs Bytes conversion:
Network speeds are in bits/s, storage throughput is in bytes/s.
Divide by 8: 1 Gbps = 125 MB/s

Network SpeedData Throughput
100 Mbps12.5 MB/s
1 Gbps125 MB/s
10 Gbps1.25 GB/s
100 Gbps12.5 GB/s

Key formulas:

Throughput (bytes/s) = Network speed (bits/s) ÷ 8

Transfer time = Data size ÷ Throughput
Example: 1 GB over 1 Gbps = 1024 MB ÷ 125 MB/s ≈ 8 seconds

Bandwidth needed = Data size × Requests per second
Example: 1 MB responses × 1000 RPS = 1 GB/s = 8 Gbps

With compression (typical 3× reduction):
Effective bandwidth = Raw bandwidth × Compression ratio
Example: 1 Gbps × 3 = 3 Gbps effective for compressible data

Quick Mental Math Rules

RuleValue
Seconds in a day86,400 ≈ 100K
Seconds in a month~2.5 million
Seconds in a year~31.5 million ≈ π × 10⁷
1 million req/day → RPS~12
1 billion req/month → RPS~400

Key formulas:

Storage estimation:
Total storage = Object size × Number of objects × Replication factor × Time period

Example: 1 million users × 10 KB profile × 3 replicas = 30 GB

Storage growth/year = Daily new data × 365
Example: 100 GB/day × 365 = 36.5 TB/year

Bandwidth estimation:
Peak bandwidth = Average bandwidth × Peak factor (typically 2-10×)
Daily bandwidth = Average request size × Daily requests

QPS/RPS estimation:
Average QPS = Total requests ÷ Time period in seconds
Peak QPS = Average QPS × Peak factor (typically 2-3×)

Cache size estimation:
Cache size = Working set × Object size
Working set = Total objects × Access frequency factor (typically 20%)

Example: 1M users, 20% daily active, 10 KB each = 2 GB cache

Number of servers:
Servers needed = Peak QPS ÷ QPS per server
Add 30% headroom for failover

Example: 10,000 QPS ÷ 1,000 QPS/server × 1.3 = 13 servers

Time Units

UnitIn Seconds
1 nanosecond (ns)10⁻⁹ s
1 microsecond (µs)10⁻⁶ s
1 millisecond (ms)10⁻³ s

Powers of Two

PowerValueApprox.Binary (IEC)Decimal (SI)
2¹⁰1,024~1 thousand1 KiB1 KB
2²⁰1,048,576~1 million1 MiB1 MB
2³⁰1,073,741,824~1 billion1 GiB1 GB
2⁴⁰1,099,511,627,776~1 trillion1 TiB1 TB
2⁵⁰~1 quadrillion1 PiB1 PB

Binary (IEC) vs Decimal (SI) Units

Binary (IEC)Exact ValueDecimal (SI)Exact ValueDifference
1 KiB (kibibyte)1,024 bytes1 KB (kilobyte)1,000 bytes2.4%
1 MiB (mebibyte)1,048,576 bytes1 MB (megabyte)1,000,000 bytes4.9%
1 GiB (gibibyte)1,073,741,824 bytes1 GB (gigabyte)1,000,000,000 bytes7.4%
1 TiB (tebibyte)1,099,511,627,776 bytes1 TB (terabyte)1,000,000,000,000 bytes10.0%
1 PiB (pebibyte)1,125,899,906,842,624 bytes1 PB (petabyte)1,000,000,000,000,000 bytes12.6%

Usage conventions:

  • RAM & memory: Usually binary (a “16 GB” RAM stick is really 16 GiB)
  • Storage (HDD/SSD): Usually decimal (a “1 TB” drive is 1,000 GB, not 1,024 GB)
  • Network speeds: Always decimal (1 Gbps = 1,000,000,000 bits/s)
  • Linux tools: ls -l shows bytes; use ls -lh for human-readable (binary)

Key formulas:

1 KiB = 2¹⁰ bytes = 1,024 bytes
1 MiB = 2²⁰ bytes = 1,024 KiB ≈ 1.049 MB
1 GiB = 2³⁰ bytes = 1,024 MiB ≈ 1.074 GB
1 TiB = 2⁴⁰ bytes = 1,024 GiB ≈ 1.100 TB
1 PiB = 2⁵⁰ bytes = 1,024 TiB ≈ 1.126 PB

Quick estimate: 2¹⁰ ≈ 10³ (off by 2.4%)
Therefore: 2ⁿ ≈ 10^(n × 0.3)

Converting binary to decimal:
GiB to GB: multiply by 1.074
TiB to TB: multiply by 1.100

Example: 500 GiB SSD = 500 × 1.074 = 537 GB
Example: "1 TB" HDD = 1000 GB = 931 GiB (what OS shows)

Database & Cache Latencies

OperationLatencyNotes
Redis GET (local)0.1–0.5 msIn-memory, same datacenter
Redis GET (cross-AZ)1–2 msNetwork overhead
Memcached GET0.1–0.5 msSimilar to Redis
PostgreSQL simple query1–5 msIndexed, warm cache
PostgreSQL complex query10–100+ msJoins, aggregations
MySQL simple query1–5 msIndexed, warm cache
MongoDB document fetch1–5 msBy _id, indexed
Elasticsearch query10–50 msDepends on index size
SQLite (local file)0.01–0.1 msNo network overhead

Key formulas:

Cache hit ratio:
Hit ratio = Cache hits ÷ (Cache hits + Cache misses)
Target: > 90% for effective caching

Average latency with cache:
Avg latency = (Hit ratio × Cache latency) + ((1 - Hit ratio) × DB latency)

Example: 95% hit ratio, 1ms cache, 10ms DB
= (0.95 × 1) + (0.05 × 10) = 0.95 + 0.5 = 1.45 ms

Cache capacity planning:
Memory needed = Number of cached items × Average item size × Overhead (1.2-1.5×)

Database connections:
Max connections = (Number of servers × Connections per server)
Rule of thumb: PostgreSQL handles ~100-500 connections well
Use connection pooling (PgBouncer) for more

IOPS estimation:
Required IOPS = QPS × Queries per request × (1 + Cache miss ratio)

Cloud Storage Latencies

OperationLatencyNotes
S3 / GCS first byte (same region)20–100 msVaries by object size
S3 / GCS GET (small object)50–200 ms< 1 MB
S3 / GCS GET (large object)Throughput-limited~100 MB/s per connection
S3 / GCS PUT100–300 msSingle-part upload
S3 / GCS LIST (1000 objects)100–300 msPagination adds latency
CloudFront / CDN edge hit5–20 msDepends on user location
CDN cache miss+50–150 msOrigin fetch added

Cloud storage throughput:

  • Single S3 connection: ~100 MB/s
  • Multi-part parallel upload: 1–5 GB/s achievable
  • S3 request rate: ~5,500 PUT/s, ~5,500 GET/s per prefix

Key formulas:

S3 cost estimation:
Storage cost = GB stored × $0.023/GB/month (standard tier)
Request cost = (PUT requests × $0.005/1000) + (GET requests × $0.0004/1000)
Transfer cost = GB transferred out × $0.09/GB (to internet)

CDN cost estimation:
CDN cost = GB transferred × $0.085/GB (first 10TB)
Savings = Origin requests avoided × Origin cost per request

Multipart upload calculation:
Parts needed = File size ÷ Part size (min 5MB, max 5GB)
Upload time = File size ÷ (Parallel connections × Per-connection throughput)

Example: 10 GB file, 10 parallel connections, 100 MB/s each
= 10,000 MB ÷ (10 × 100 MB/s) = 10 seconds

Typical Payload Sizes

Data TypeTypical SizeNotes
Tweet / short text250–500 bytesWith metadata
JSON overhead per field10–20 bytesKey names, quotes, delimiters
Protobuf overhead2–5 bytes/field~3–5× smaller than JSON
Average web page2–3 MBWith images, JS, CSS
HTML document only50–100 KBWithout assets
Small profile image10–50 KBCompressed JPEG/WebP
High-res photo2–5 MBJPEG
1 min video (720p)50–100 MBCompressed
1 min video (1080p)100–200 MBCompressed
1 min audio (MP3)1–2 MB128 kbps
Average email50–100 KBWith headers, no attachments
Log line200–500 bytesTypical structured log
Kafka message (typical)1–10 KBVaries by use case

Key formulas:

Image size estimation:
Uncompressed = Width × Height × Bytes per pixel (3 for RGB, 4 for RGBA)
Example: 1920×1080×3 = 6.2 MB uncompressed
Compressed JPEG ≈ Uncompressed ÷ 10 = ~600 KB

Video size estimation:
Bitrate (Mbps) × Duration (seconds) ÷ 8 = Size in MB
Example: 5 Mbps × 60 sec ÷ 8 = 37.5 MB

Audio size estimation:
Bitrate (kbps) × Duration (seconds) ÷ 8 = Size in KB
Example: 128 kbps × 60 sec ÷ 8 = 960 KB ≈ 1 MB

Log storage estimation:
Daily logs = Log lines per second × 86,400 × Avg log size
Example: 1000 logs/sec × 86,400 × 300 bytes = 25.9 GB/day

JSON vs Protobuf:
Protobuf size ≈ JSON size × 0.3
Protobuf parse time ≈ JSON parse time × 0.1

Serialization Format Comparison

FormatSizeEncode SpeedDecode SpeedHuman Readable
JSONBaselineMediumMedium✅ Yes
Protobuf0.3–0.5×FastFast❌ No
MessagePack0.5–0.7×FastFast❌ No
Avro0.3–0.5×FastFast❌ No
XML1.5–2×SlowSlow✅ Yes
CSV0.5–0.8×FastMedium✅ Yes

Common System Capacities

ComponentTypical LimitNotes
Single Redis instance100K–1M ops/sDepends on operation type
Single PostgreSQL10K–50K queries/sSimple queries, good hardware
Single MySQL10K–50K queries/sSimilar to PostgreSQL
Single Kafka broker100K–500K msgs/sDepends on message size
Single Nginx10K–100K req/sStatic content
Single Node.js10K–30K req/sI/O bound workloads
TCP connections per server~65K per IPPort exhaustion limit
Open file descriptors1M+ (tunable)ulimit -n

Key formulas:

Connection limits:
Max TCP connections = 65,535 per IP (port range)
With multiple IPs: Max connections = 65,535 × Number of IPs

Thread pool sizing (CPU-bound):
Optimal threads = Number of CPU cores

Thread pool sizing (I/O-bound):
Optimal threads = Number of cores × (1 + Wait time / Service time)
Example: 8 cores, 100ms wait, 10ms service = 8 × (1 + 10) = 88 threads

Little's Law (queue sizing):
L = λ × W
L = Average number in system
λ = Arrival rate (requests/second)
W = Average time in system

Example: 1000 RPS, 100ms latency → 1000 × 0.1 = 100 concurrent requests

Amdahl's Law (parallelization speedup):
Speedup = 1 / ((1 - P) + P/N)
P = Parallelizable fraction
N = Number of processors

Example: 90% parallelizable, 10 cores → 1 / (0.1 + 0.9/10) = 5.26× speedup

Message Queue Comparison

SystemThroughputLatencyOrderingNotes
Kafka500K–1M msgs/s2–10 msPer-partitionBest for high throughput, replay
RabbitMQ20K–50K msgs/s1–5 msPer-queueBest for complex routing
Amazon SQS3K msgs/s (standard)10–50 msBest-effortFully managed, scales infinitely
Amazon SQS FIFO300 msgs/s10–50 msStrict FIFOUse for ordering guarantees
Redis Streams100K+ msgs/s< 1 msPer-streamGood for simple pub/sub
Google Pub/Sub100K+ msgs/s10–50 msPer-topicFully managed, global

When to use what:

  • Kafka: Event sourcing, log aggregation, high-throughput streaming
  • RabbitMQ: Task queues, complex routing, RPC patterns
  • SQS: Serverless, simple decoupling, no ops overhead
  • Redis Streams: Low-latency, already using Redis

Container & Kubernetes Overhead

OperationLatency/OverheadNotes
Container startup (Docker)500 ms – 2 sDepends on image size
Container startup (from cache)100–500 msImage layers cached
Pod scheduling (K8s)1–5 sIncludes image pull if not cached
Pod scheduling (cached image)500 ms – 2 sNo image pull
K8s Service DNS resolution1–10 msCoreDNS lookup
K8s ConfigMap/Secret mount100–500 msAt pod startup
Sidecar proxy overhead (Istio)1–3 msPer request
Container memory overhead10–50 MBRuntime + base OS
K8s per-pod overhead~100 MBkubelet, pause container

Cold start times (serverless):

PlatformCold StartNotes
AWS Lambda (Python/Node)100–500 msLightweight runtimes
AWS Lambda (Java/.NET)500 ms – 3 sJVM/CLR startup
AWS Lambda (with VPC)+200–500 msENI attachment
Google Cloud Functions100–500 msSimilar to Lambda
Cloudflare Workers< 5 msV8 isolates, no container

DNS & TLS Overhead

OperationLatencyNotes
DNS lookup (cached)0–1 msOS or browser cache
DNS lookup (recursive)20–100 msFull resolution
DNS lookup (authoritative)10–50 msDirect to nameserver
DNS TTL (typical)60–300 sBalance freshness vs. latency
TLS handshake (TLS 1.2)2 RTT~100–300 ms cross-region
TLS handshake (TLS 1.3)1 RTT~50–150 ms cross-region
TLS resumption0–1 RTTSession tickets
mTLS overhead+1–5 msCertificate verification
Certificate verification1–10 msOCSP/CRL checks can add more

Optimization tips:

  • Use HTTP/2 or HTTP/3 — multiplexing reduces connection overhead
  • Enable TLS session resumption — avoids full handshake
  • Use connection pooling — reuse existing connections
  • Pre-resolve DNS — dns-prefetch hint in browsers
  • Keep-alive connections — avoid TCP + TLS setup per request

Cost Ballpark (Cloud, 2025)

ResourceApproximate CostNotes
Compute (on-demand)$0.04–0.10/hr per vCPUAWS/GCP/Azure
Compute (spot/preemptible)$0.01–0.03/hr per vCPU60–80% savings
Memory$0.005/GB/hrIncluded with compute
S3/GCS storage$0.02–0.03/GB/monthStandard tier
S3/GCS requests$0.0004/1K GETsPUTs cost more
Data transfer (egress)$0.05–0.12/GBInter-region/internet
Data transfer (same region)Free–$0.01/GBSame AZ often free
Managed Kafka$0.10–0.20/hr per brokerMSK, Confluent
Managed Redis$0.02–0.05/GB/hrElastiCache
Managed PostgreSQL$0.02–0.10/hr per vCPURDS
Lambda invocation$0.20/1M requests+ duration cost
API Gateway$1–3.50/1M requestsDepends on tier

Rule of thumb: Egress costs often dominate — design to minimize cross-region and internet data transfer.


Common Data Type Sizes

Primitive Types (C/Java/Go)

TypeSizeRange/Notes
bool1 bytetrue/false
char1 byte-128 to 127
short2 bytes-32K to 32K
int4 bytes-2.1B to 2.1B
long8 bytes-9.2 quintillion to 9.2 quintillion
float4 bytes~7 decimal digits precision
double8 bytes~15 decimal digits precision
Pointer (64-bit)8 bytesMemory address

PostgreSQL Numeric Types

TypeSizeRange/Notes
smallint2 bytes-32,768 to 32,767
integer4 bytes-2.1B to 2.1B
bigint8 bytes-9.2 quintillion to 9.2 quintillion
serial4 bytesAuto-increment (1 to 2.1B)
bigserial8 bytesAuto-increment (1 to 9.2 quintillion)
decimal/numericVariableUp to 131,072 digits; exact precision
real4 bytes6 decimal digits precision
double precision8 bytes15 decimal digits precision
money8 bytes-92 quadrillion to 92 quadrillion

PostgreSQL String Types

TypeSizeNotes
char(n)n bytesFixed-length, space-padded
varchar(n)Up to n + 1–4 bytesVariable-length with limit
textVariableUnlimited length
byteaVariableBinary data (byte array)

String storage: 1–4 bytes overhead + actual string length. Strings > 2KB are automatically compressed (TOAST).

PostgreSQL Date/Time Types

TypeSizeRange/Notes
timestamp8 bytes4713 BC to 294276 AD; microsecond precision
timestamptz8 bytesSame + timezone aware
date4 bytes4713 BC to 5874897 AD
time8 bytes00:00:00 to 24:00:00; microsecond precision
timetz12 bytesTime with timezone
interval16 bytesTime span

PostgreSQL Other Common Types

TypeSizeNotes
boolean1 bytetrue/false/null
uuid16 bytes128-bit universally unique identifier
jsonVariableStored as text, parsed on access
jsonbVariableBinary JSON, faster queries, ~10–20% larger
inet7 or 19 bytesIPv4 or IPv6 address
cidr7 or 19 bytesIPv4 or IPv6 network
macaddr6 bytesMAC address
point16 bytes2D point (x, y)
box32 bytesRectangular box
array24 bytes + dataArray header + element storage
hstoreVariableKey-value pairs
tsvectorVariableFull-text search document
tsqueryVariableFull-text search query

Common Identifiers

TypeSizeNotes
UNIX timestamp4 bytesSeconds since 1970 (until 2038)
UNIX timestamp (64-bit)8 bytesMilliseconds, no 2038 problem
UUID16 bytes128-bit, globally unique
ULID16 bytesUUID + timestamp, sortable
Snowflake ID8 bytesTwitter-style, sortable
MongoDB ObjectId12 bytesTimestamp + machine + process + counter
Auto-increment int4 bytes~2.1B max IDs
Auto-increment bigint8 bytes~9.2 quintillion max IDs

Key formulas:

UUID collision probability (Birthday Problem):
P(collision) ≈ 1 - e^(-n² / 2 × 2¹²²)
For 1 billion UUIDs: P ≈ 10⁻¹⁸ (effectively zero)

ID space exhaustion:
Time to exhaust = Max IDs ÷ IDs per second
32-bit at 1000/s = 2.1B ÷ 1000 = 24 days
64-bit at 1M/s = 9.2 quintillion ÷ 1M = 292,000 years

Snowflake ID structure (64-bit):
- 1 bit: sign (always 0)
- 41 bits: timestamp (69 years from epoch)
- 10 bits: machine ID (1024 machines)
- 12 bits: sequence (4096 IDs/ms/machine)
Max: 4096 × 1000 × 1024 = 4.2 billion IDs/second globally

PostgreSQL Row Overhead

ComponentSizeNotes
Tuple header23 bytesPer row
NULL bitmap1 byte per 8 columnsTracks NULL values
Alignment padding0–7 bytes8-byte alignment
TOAST pointer18 bytesFor large values stored externally

Key formulas:

Row size estimation:
Row size = 23 bytes (header) + NULL bitmap + Column data + Padding

Table size estimation:
Table size = Number of rows × Average row size × Bloat factor (1.2-1.5)

Index size estimation:
B-tree index ≈ Number of rows × (Key size + 8 bytes) × 2-3× overhead
Example: 10M rows, 8-byte key = 10M × 16 × 2.5 = 400 MB

TOAST threshold: Values > 2KB are compressed/stored externally

Pages and blocks:
PostgreSQL page size = 8 KB
Rows per page ≈ 8192 ÷ Row size (minus page header ~24 bytes)
Example: 100-byte rows → ~80 rows per page

Fill factor (default 90% for tables):
Usable space per page = 8192 × 0.9 = 7373 bytes