Multiplayer Game Networking: Authoritative Servers, Prediction, and Lag Compensation
Multiplayer games solve a distributed systems problem harsher than anything in enterprise software: dozens of replicas (players) mutating shared state at 60Hz, over links with 20-150ms latency and real packet loss, where users perceive 100ms of delay as "broken" and any client can be a cheater. The solutions the games industry converged on — authoritative servers, client prediction with rollback, lag compensation — are consistency-model engineering under a latency budget no database would accept, and they make a fantastic systems interview precisely because none of the usual answers (retry, queue, eventual consistency) survive contact.
The trust model decides the topology
Peer-to-peer died for one reason: the client is in the attacker's hands. The standard model is the authoritative server: clients send inputs (not state — never state), the server simulates the world at a fixed tick rate (say 60Hz), and broadcasts snapshots. Cheating by state manipulation becomes impossible by construction; what remains (aimbots, wallhacks from leaked info) is fought elsewhere. Deterministic lockstep — everyone simulates identical ticks from everyone's inputs, only inputs on the wire — survives in RTS games (thousands of units, tiny bandwidth) but demands bit-perfect determinism and runs at the slowest player's latency, which is why action games abandoned it.
client -> {input seq=812: forward+jump, aim} (UDP, unreliable, 60/s)
server: simulate tick 812 from all inputs -> world snapshot 812
server -> clients: delta(snapshot 812, last-acked) (~20/s, interpolated)
Transport is UDP with a custom reliability layer: a lost movement packet must not be retransmitted (its information is stale by arrival — TCP's in-order guarantee is actively harmful, one loss stalls everything behind it); a lost "you bought a sword" event must be. Per-channel semantics — unreliable-sequenced for state, reliable-ordered for events — is the transport design, and naming that split is the first senior signal.
Hiding latency: prediction and reconciliation
Waiting a round-trip to see your own movement is unplayable. Client-side prediction: apply your input locally immediately, while it travels to the server. The server's authoritative result arrives ~100ms later — for a state your client already left. Reconciliation: the client keeps a buffer of unacknowledged inputs; on each server snapshot, it rewinds to the server's state and replays pending inputs on top.
client tick 850: predicted position from inputs 812-850
server snapshot for tick 812 arrives, disagrees slightly
-> rollback to server@812, re-simulate inputs 813-850 (a few ms of CPU)
-> tiny corrections smoothed; big ones = the "rubber-band" you've felt
That rewind-and-replay is optimistic concurrency control with compensation — the client speculates, the server adjudicates, divergence gets repaired by replay (the durable-workflow post's replay trick at 60Hz). Other players can't be predicted (their inputs are unknown), so remotes are rendered ~100ms in the past, interpolated between two received snapshots — smooth motion bought with staleness.
Which creates the famous paradox: you aim at where you see an opponent — 100ms behind their true position. Lag compensation: the server keeps a short history ring of world states; when your shot arrives stamped "fired at tick 850 seeing snapshot 844," the server rewinds the world to what you saw and adjudicates the hit there. You hit what you aimed at ("favor the shooter"); the cost is the victim's experience — shot after reaching cover, because on the shooter's screen you hadn't yet. That asymmetry is a product decision about whose latency hurts — consistency-model choice as game feel, the sharpest example anywhere that "which anomaly do you tolerate" is a design axis.
Scale: interest management and the fleet
Bandwidth per client is (snapshot size × rate), so servers send each client only what it can perceive: interest management — spatial partitioning (grids, AOI radii) filtering entities per client, priority-scored by relevance (nearby enemy > distant teammate), plus delta compression against the last acknowledged snapshot per client (send diffs, with periodic keyframes — video encoding's playbook applied to world state). Big worlds shard geographically across server processes with handoff at boundaries (MMO zoning; seamless worlds interleave authority at the seams — the hard mode).
The fleet side is its own system: matchmaking (queue by skill/region/mode — an assignment problem balancing wait time vs match quality vs ping), session allocation (game servers as ephemeral pods — Agones-style orchestration: allocate, run one match, die; bin-packing sessions onto hosts), and a relay/NAT layer so consoles behind CGNAT connect at all. Server ticks are the unit of capacity: a tick overrunning its 16ms budget cascades into simulation debt — the matching engine's "deterministic serial core with a hard deadline," except here there are ten thousand of them.
| Interview probe | Answer sketch |
|---|---|
| Why not TCP? | Head-of-line blocking: one lost packet delays everything after it; games need newest-wins, not all-in-order |
| Cheater sends "I'm at X"? | Clients send inputs only; server validates physics (speed caps, LOS) — authority is the anti-cheat foundation, detection handles the rest |
| 128-tick vs 60-tick? | Halves worst-case input-to-adjudication latency, doubles CPU/bandwidth — a cost/feel dial, and esports pays it |
| Fighting-game netcode? | Rollback netcode = both sides predict, rewind on real input arrival — GGPO's trick; works when simulation is cheap and deterministic |
The transferable frame: authority where trust lives, speculation where latency hurts, replay to reconcile, staleness rendered smooth, and history kept so late information can be judged in its own time frame. Games solved read-your-writes, causal ordering, and compensation under a 16-millisecond budget — it's the most demanding consistency engineering most engineers have never studied.
Keep reading
Write Skew: The Anomaly Snapshot Isolation Does Not Catch
Two transactions each read what the other writes, both commit, and an invariant dies. Snapshot isolation allows write skew — here is how to close the hole.
Designing a Shopping Cart: Price Snapshots, Merge, and No Inventory Hold
A cart is a per-user document, not a reservation. What to store on the line, how to merge an anonymous cart at login, and when the price is allowed to change.
Designing Snowflake-Style IDs: Ordering, Workers, and Clock Rollback
A 64-bit id from a timestamp, a worker number, and a per-millisecond sequence. How many you can issue, why the clock must not step backwards, and why JavaScript cannot hold one.
PostgreSQL 19 on October 29: WAIT for Read-Your-Writes, REPACK Without the Lock, and What Got Pulled
PostgreSQL 19 GA is scheduled for October 29, 2026. The WAIT command gives standbys read-your-writes, REPACK CONCURRENTLY replaces VACUUM FULL and CLUSTER, autovacuum goes parallel, and SQL/PGQ, online checksums, and FOR PORTION OF were reverted in Beta 4.
Idempotency Keys for Write APIs
How to make POST safe to retry: the key, the stored response, the race between two identical requests, and the expiry that forgets too soon.
Read-Your-Writes: The User Just Saved and the Read Replica Does Not Know
Why a write to the primary followed by a read from a replica shows stale data, and the practical ways to pin the next read without sending all traffic to the primary.
Newsletter
New posts, straight to your inbox
One email per post. No spam, no tracking pixels, unsubscribe anytime.
Comments
- No comments yet. Be the first.