CASE FILE NO. 05 - SYSTEM DESIGN SERIES

The Case of the
Lost Message

Two machines, a thousand miles apart, need to understand each other perfectly, over a wire that drops things, delays things, and occasionally forgets you exist. Everything on this board is how that still works.

1 · First principles 2 · Mechanism 3 · Decision space 4 · Real systems 5 · Failure modes 6 · Scale 7 · Reference table 8 · Interrogation
1 First principles

Why does this problem even exist?

Two computers exchanging data need to agree on an enormous number of things at once: how bits become voltages on a wire, how those bits are grouped, how to find the other machine at all, how to notice and fix lost data, and finally what the data actually means. Solving all of that in one giant tangled step would be unmaintainable - nobody could change how packets are routed without also risking how web pages render.

The fix is the same idea behind every well-designed system: split it into layers, each solving exactly one problem, each only trusting the layer directly below it. That's the entire reason the OSI and TCP/IP models exist. Everything else in this file - DNS, HTTP, proxies, retries - is a specific answer to a specific layer's problem.

"Each layer only needs to keep one promise to the layer above it - nothing more."
2 Core mechanism - run it yourself

The layers, side by side

OSI has 7 layers, mostly used as a teaching/reference model. Real-world networking runs on the simpler 4-layer TCP/IP model - most engineers think in this one day to day.

OSI (7 layers)

7 · Application HTTP, DNS
6 · Presentation TLS, encoding
5 · Session sockets
4 · Transport TCP, UDP
3 · Network IP, routing
2 · Data Link Ethernet, MAC
1 · Physical cables, radio

TCP/IP (4 layers) - what you actually use

Application HTTP, DNS, TLS
Transport TCP, UDP
Internet IP
Link Ethernet, Wi-Fi

Mental model: it's an envelope inside an envelope. Application data gets wrapped with a TCP header, that gets wrapped with an IP header, that gets wrapped with a link-layer header. Each layer on the receiving end only opens its own envelope and hands the contents up.

Status: cache empty
Client Resolver (cache) Root NS .com TLD Authoritative NS
First lookup walks the full chain. Resolve again before clearing the cache to see it answered instantly.
Protocol
HTTP HTTPS
Round trips before data: 1
Client Server
HTTP: 1 round trip (TCP handshake) before your GET request even leaves. HTTPS adds a TLS handshake on top of that.
Connection
Keep-Alive ON Keep-Alive OFF
Client Server
With Keep-Alive on, one connection serves all 3 requests. Off, each request pays a fresh handshake.

Proxies vs. reverse proxies vs. API gateways - who stands where

Forward proxy - hides the client

Client Fwd Proxy Server Server never sees the real client

Reverse proxy - hides the server(s)

Client Reverse Proxy Srv A Srv B Client never knows which server answered

An API gateway is a reverse proxy that also understands the application: it routes by API path/version, checks auth tokens, applies rate limits, and sometimes combines several backend calls into one response - a plain reverse proxy just forwards bytes.

3 The full decision space

Tap any card to open the evidence.

4 Witness statements - real systems

NGINX / HAProxy

The default reverse proxies and load balancers for a huge share of the web - SSL termination, caching, request routing, all in one process in front of your app servers.

Cloudflare / Fastly / Akamai

Reverse proxy + CDN combined at global scale - terminate TLS, cache static content, and absorb DDoS traffic before it ever reaches origin servers.

Kong / AWS API Gateway

Purpose-built API gateways: auth, rate limiting, routing to backend services, request/response transformation, all managed as configuration rather than code.

Netflix Zuul

Netflix's own edge/API gateway service, built specifically to handle routing, monitoring, and resilience at their scale.current status unverified

Google Public DNS / Cloudflare 1.1.1.1

Public recursive DNS resolvers built for speed and privacy, used as alternatives to an ISP's default (often slower, sometimes less private) resolver.

Squid

A long-standing, classic forward proxy - often used by organizations for content filtering, caching, and monitoring outbound traffic.

5 Red flags - what breaks this

DNS propagation delay

Change a DNS record and it can take up to its TTL for every cached copy worldwide to notice. Deploy-day surprise if not planned for.

Retry storms

Every client retrying a failing service at the same instant, with no backoff, doubles or triples the load on a service that's already struggling - often what actually causes an outage, not the original blip.

Timeout misconfiguration

Too short: healthy-but-slow requests get killed and retried needlessly. Too long: a hung downstream call ties up resources until the whole service starves.

TLS certificate expiry

An expired cert doesn't degrade gracefully - it hard-fails every HTTPS connection the moment it lapses. A famous, entirely preventable class of outage.

Reverse proxy as a new SPOF

Put one reverse proxy in front of everything and you've built a new single point of failure - same lesson as the load balancer needing its own HA story.

Connection pool exhaustion

No Keep-Alive (or a pool sized too small) means connections are opened faster than they're released, until new requests simply can't get one.

Head-of-line blocking

In HTTP/1.1, one slow request on a connection blocks everything queued behind it. HTTP/2 fixes this at the HTTP layer but can still stall at the TCP layer - HTTP/3 (QUIC, over UDP) is the fix for that remaining case.

6 Scale & numbers

A cross-region TCP handshake costs roughly one round trip - say 100ms. HTTPS adds a TLS handshake on top - another 100ms (modern TLS 1.3; older TLS 1.2 could cost double that). Without Keep-Alive, that 200ms tax is paid again on every single request.

10 req
Without Keep-Alive: 10 × 200ms = 2s of pure handshake overhead, before any actual data transfer. With Keep-Alive: 200ms once, reused for all 10.
1,000 req
Without Keep-Alive: 200 seconds of handshake overhead alone. This is the exact reason Keep-Alive isn't a minor optimization - at real traffic volume it dominates the entire latency budget.

The design decision this forces: at low request volume the handshake cost barely matters. Past a certain request rate, connection reuse stops being a nice-to-have and becomes the majority of your latency budget if skipped.

7 Reference sheet
DecisionOptionsPick based on
Transport protocolTCP / UDPNeed guaranteed, ordered delivery → TCP. Need raw speed, can tolerate loss → UDP
HTTP vs HTTPSPlaintext / TLS-encryptedAlways HTTPS in production - the "trade-off" is a small fixed handshake cost, not a real choice anymore
HTTP versionHTTP/1.1 / HTTP/2 / HTTP/3Legacy compatibility → 1.1. Multiplexed streams over TCP → 2. Avoid TCP-level head-of-line blocking too → 3 (QUIC/UDP)
Proxy typeForward / reverseHide/control the client's outbound traffic → forward. Hide/balance across your own servers → reverse
DNS TTLShort / longNeed fast failover or frequent IP changes → short TTL. Stability, fewer lookups → long TTL
Retry strategyNone / fixed / exponential backoff + jitterIdempotent operation, flaky dependency → backoff + jitter. Non-idempotent → be very careful, or don't retry at all
Gateway vs plain proxyAPI gateway / reverse proxyNeed auth, rate limiting, routing by API semantics → gateway. Just need to forward/balance traffic → plain reverse proxy
Connection reuseKeep-Alive on / offAlmost always on in production - off only for deliberately one-shot, rare connections
8 The interrogation