Skip to content

2. Building Blocks

The standard pieces almost every large design is assembled from. Cloud-specific versions are in AWS Elastic Load Balancing and Azure and GCP Edge Delivery. Back to Fundamentals. Sidecar, ambassador and readiness-probe style patterns are in Distributed Patterns.

At a glance

Block Solves Common tools
DNS Name to IP, geo routing Route 53, Cloud DNS, Cloudflare
Load balancer Spread traffic, hide failures Nginx, HAProxy, ALB/NLB
Cache Cut latency and DB load Redis, Memcached
CDN Serve static content near users CloudFront, Cloudflare, Akamai
Message queue Decouple and absorb bursts Kafka, RabbitMQ, SQS
API gateway Auth, rate limit, routing in one place Kong, API Gateway, Envoy
Object storage Large files and media S3, Blob Storage, GCS

Load balancing

flowchart LR
    C[Clients] --> LB{Load balancer}
    LB --> W1[Web 1]
    LB --> W2[Web 2]
    LB --> W3[Web 3 - failed]
    W1 --> DB[(Database)]
    W2 --> DB
    LB -. health check fails .-> W3
  • Clients talk to the balancer's address; backends can use private IPs.
  • Health checks remove dead servers; the balancer routes around them.
  • Algorithms
  • Round robin: take turns. Fine when requests cost about the same.
  • Least connections: send to the least busy. Better for long requests.
  • IP hash: the same client always lands on the same server (sticky).
  • Weighted: bigger servers get more.
  • Layer 4 balances on IP and port (fast). Layer 7 reads HTTP, so it can route by path or host (/api vs /static).
  • The balancer itself must not be a single point of failure: run a pair (active/passive or active/active).

Caching

sequenceDiagram
    participant App
    participant Cache as Cache (Redis)
    participant DB
    App->>Cache: GET user:42
    alt hit
        Cache-->>App: data
    else miss
        Cache-->>App: nil
        App->>DB: SELECT ... WHERE id=42
        DB-->>App: row
        App->>Cache: SET user:42 (TTL 300s)
    end

This is cache-aside (lazy loading), the most common pattern.

Strategy How it works Trade-off
Cache-aside App checks cache, falls back to DB, fills cache Simple; first read is slow, data can go stale
Read-through Cache fetches from DB itself Cleaner app code; cache must know the DB
Write-through Write to cache and DB together Always fresh; slower writes
Write-back Write to cache, flush to DB later Fast writes; data loss if cache dies first

Eviction when full: LRU (least recently used, the usual default), LFU (least frequently used), FIFO.

$ redis-cli SET user:42 '{"name":"Sam"}' EX 300     # expires in 5 minutes
$ redis-cli GET user:42
$ redis-cli TTL user:42
  • Cache data that is read often and changes rarely. Do not cache data that must always be exact.
  • Set a TTL so stale entries expire.
  • Cache stampede: a hot key expires and thousands of requests hit the DB at once. Fix with request coalescing or a lock so only one request refills it.
  • Invalidation (knowing when cached data is wrong) is the hard part.

CDN

flowchart LR
    U1[User in Cape Town] --> E1[Edge server Johannesburg]
    U2[User in London] --> E2[Edge server London]
    E1 -- miss --> O[(Origin server)]
    E2 -- miss --> O
  • Edge servers close to users cache static files (images, CSS, JS, video).
  • First request is a miss and goes to the origin; later ones are served from the edge.
  • Control freshness with Cache-Control: max-age=... headers, or purge and use versioned file names (app.v3.js).
  • Related note on static hosting: Static Sites on Cloudflare.

Message queues

flowchart LR
    P1[Producer: web API] --> Q(["Queue"])
    P2[Producer: scheduler] --> Q
    Q --> C1[Worker 1]
    Q --> C2[Worker 2]
    Q --> C3[Worker 3]
  • The producer drops a message and carries on; consumers process at their own pace.
  • Why: decouple services, smooth traffic spikes, retry failed work, scale workers independently.
  • Example: photo upload. The API stores the file and enqueues resize(photo_id); workers create thumbnails later, so the user does not wait.
  • Queue vs log: SQS/RabbitMQ delete a message once handled. Kafka keeps an ordered log that many consumers can replay.
  • Delivery guarantees: at-most-once, at-least-once (usual), exactly-once (hard). With at-least-once, make consumers idempotent (handling a message twice is harmless).
  • A dead-letter queue holds messages that keep failing so they can be inspected.

API gateway and reverse proxy

  • One entry point for clients: authentication, TLS termination, rate limiting (Reliability Patterns), routing to the right service, logging.
  • A reverse proxy (Nginx) sits in front of servers; a forward proxy sits in front of clients.

Object storage

  • Store large blobs (images, video, backups) as objects addressed by key, not as database rows.
  • Cheap, durable (replicated), served via CDN. The database keeps only the URL or key.
  • Pre-signed URLs let a client upload straight to storage, so large files never pass through your servers.