Real-time multiplayer game (FPS / Battle Royale) — server-authoritative game servers, UDP at 60Hz tick rate, client-side prediction + reconciliation, Agones matchmaking, Kafka anti-cheat telemetry feeding an ML detector. Five animated scenarios: matchmaking + spawn, 60Hz tick loop with AOI broadcast, client prediction + reconciliation on misprediction, UDP packet-loss interpolation + FEC, aimbot detection + HWID ban. Two ADRs (UDP custom vs WebRTC vs WebSocket; server-authoritative vs lockstep). Capacity hints on every node.
Real-time multiplayer game is one of the hardest system-design cases because the system is not allowed to hide latency behind normal web tricks. In a feed, a cache miss can be 300 ms. In an FPS or battle royale, 300 ms means the player already lost the fight. The design forces you to reason about transport protocol, regional placement, authoritative state, tick loops, prediction, reconciliation, anti-cheat, matchmaking, and persistent progression as one system.
The practical requirement is usually: millions of concurrent players, regional latency below 80 ms RTT, jitter below 30 ms, packet loss around or below 1%, and match assignment within tens of seconds. At Fortnite or Counter-Strike scale, 5M concurrent players and 100-player matches mean roughly 50K active match processes. With a 60 Hz server tick, each match receives player inputs and broadcasts compressed deltas continuously. That is not an HTTP CRUD workload. It is a real-time simulation platform with a control plane around it.
This case trains the core ideas behind ::concept{slug="udp"}, ::concept{slug="websocket"}, ::concept{slug="partitioning-strategies"}, regional routing, and event telemetry. It also explains why game backends separate lobby/control traffic from in-match traffic.
Think of the architecture as two planes. The control plane is slow compared to the game loop: login, region probing, matchmaking, party/lobby state, inventory, XP, ELO, and match history. This plane can use HTTPS, WebSocket, Postgres, Cassandra, Redis, queues, and normal retries.
The data plane is the active match. A dedicated game server owns the truth for one match. Clients send input packets: move, aim, fire, use item, sequence number, timestamp. The server advances the world at a fixed tick rate, validates actions, runs physics and hit detection, then sends each player only the delta they need, often scoped by area of interest. The client predicts its own movement locally so controls feel instant, renders remote players slightly in the past to smooth jitter, and corrects itself when the server disagrees.
The key design rule is: the client is never trusted for authoritative state. It can request actions, but the server decides position, damage, health, inventory changes, score, and match result. This single rule shapes the networking, anti-cheat, and persistence model.
The diagram shows players going through a Region Locator and Matchmaker before connecting to a dedicated Game Server over UDP. The Region Locator measures or estimates latency to regions and pins the player to the closest viable region. The Matchmaker groups players by mode, party, skill, input device, region, and wait time. Once enough compatible players are found, it assigns or spawns a match server and returns a connection endpoint plus a short-lived secret.
The Game Server group contains the authoritative UDP server and in-game Redis used for hot snapshots and short reconnect windows. Persistent profile data lives outside the match process: Postgres for player profile, XP, ELO, and inventory; Cassandra or another wide-column store for denormalized match history. Anti-cheat is intentionally off the critical path: the server streams telemetry to Kafka, ML detection flags suspicious behavior, and a ban service acts on high-confidence signals.
This split is important. The match server must not synchronously wait on profile databases or ML systems during each tick. It should keep the tick loop stable and push durable side effects asynchronously or at safe boundaries such as match end.
Matchmaking and spawn show that WebSocket or HTTP is fine for lobby state but not for the match loop. The player asks where to play, receives a region, enters an ELO queue, gets assigned to a server, and completes a UDP handshake. The lesson is that latency-aware placement is a product feature, not only an infrastructure detail.
The 60 Hz tick loop shows the hot path: client input, server simulation, hit detection, AOI-filtered delta broadcast, and periodic checkpoint to Redis. The server does not broadcast the full world to every player. It sends compressed updates relevant to each player to reduce bandwidth and CPU.
Prediction and reconciliation teach why responsive controls are possible even with 30-80 ms RTT. The client applies its own input immediately, remembers unacknowledged inputs, and when the server sends the authoritative state, it rewinds to that state and replays pending inputs. A visible snap means either prediction drift, bad interpolation, or overloaded server tick.
Packet loss and interpolation show why UDP is chosen. Stale input packets are usually useless; retransmitting them can be worse than dropping them. For important state, the protocol can include sequence numbers, selective acknowledgements, redundancy, or forward error correction. Different packet classes deserve different reliability policies.
Aimbot detection shows the async telemetry loop. Headshot ratio, aim snap angles, reaction time, input entropy, impossible movement, and hardware fingerprints flow into Kafka and ML/rules detectors. The ban service should separate instant kicks for obvious attacks from delayed bans used to hide detection thresholds.
UDP custom protocol vs WebRTC vs WebSocket is the first trade-off. UDP gives the most control over retransmission, packet priority, binary layout, and server fleet routing. WebRTC is useful for browser games and voice, but ICE, DTLS, and TURN add complexity and overhead. WebSocket is excellent for lobby, chat, and matchmaking, but TCP head-of-line blocking makes it a poor fit for high-frequency match state.
Server-authoritative simulation vs lockstep is the second trade-off. Lockstep sends only inputs and can be elegant for deterministic RTS games with small player counts. For FPS and battle royale it ties everyone to the slowest peer, is fragile under desync, and is weaker against state manipulation. Server-authoritative simulation costs more server CPU and bandwidth, but supports cheat resistance, mid-match join, large matches, and consistent damage rules.
Persistence is also a trade-off. Saving every tick to durable storage would destroy latency and cost. Saving only final results risks losing progress after crashes. A common compromise is hot snapshots in Redis every few seconds plus durable match result events at the end.
Regional isolation improves latency but fragments matchmaking pools. Broad ELO ranges reduce queue time but can hurt fairness. Strong anti-cheat reduces abuse but can create false positives and privacy concerns. Every choice has a player-experience consequence.
Valve and Counter-Strike use dedicated authoritative servers and aggressive latency compensation. Riot Valorant is famous for server tick rate, anti-cheat investment, and regional latency targets. Fortnite combines huge battle royale matches, skill-based matchmaking, global regions, replay/match history, and massive event telemetry. Roblox and Minecraft-style platforms add another dimension: user-generated worlds and scripting, which makes sandboxing and abuse prevention part of the backend design.
The infrastructure often uses Kubernetes-like orchestration, but generic autoscaling is not enough. Game server fleets need match-aware placement, port allocation, warm pools, graceful drain, and region capacity planning. Agones and similar systems exist because one process per match has different lifecycle semantics from a stateless web pod.
The biggest mistake is putting the match loop on HTTP or WebSocket and expecting retries to solve packet loss. Retries improve correctness for business requests, but in a 60 Hz loop they can deliver stale inputs after they matter.
Another common error is trusting the client. If the client sends final position, damage, or inventory state, cheating becomes a protocol feature. The server should validate movement speed, line of sight, cooldowns, ammo, hit timing, and world bounds.
Do not put databases in the per-tick path. A Postgres write on every bullet or movement update will either collapse the DB or force the game to wait on I/O. Use memory in the match process, compact snapshots, and event streams.
Do not create global matchmaking without regional constraints. A perfect ELO match across continents is still a bad match if one player has 180 ms RTT. Also avoid making anti-cheat entirely real-time ML-dependent; detection systems fail, lag, and need human review paths.
Do not build a UDP authoritative platform for turn-based games, async board games, chat, simple party games, or collaborative tools where seconds of latency are acceptable. A conventional WebSocket or HTTP architecture is cheaper, easier to operate, and easier to secure.
Do not choose this architecture if the product cannot fund dedicated regional server capacity. A real-time game backend burns compute even when matches are short-lived, and overcommitting CPU causes tick instability that players immediately feel.
Lockstep may be a better fit for deterministic small-player RTS or simulation games where bandwidth must be tiny and all clients can wait for each other. Peer-to-peer may work for casual private sessions where cheating and fairness are not core product risks.
Read about ::concept{slug="udp"} for packet loss, ordering, and reliability policies; ::concept{slug="websocket"} for lobby/control channels; ::concept{slug="partitioning-strategies"} for regional player placement and shard ownership; ::concept{slug="caching-strategies"} for hot profile and reconnect state; and ::concept{slug="stream-processing"} for anti-cheat telemetry. For deeper practice, compare this case with large-scale chat, live video, and ride-hailing proximity systems: all are real-time, but each optimizes a different meaning of freshness.