← Module 4/Netcode taxonomy
RU
Module 4 · Online worlds (1997–2005)

Netcode taxonomy: three models

There are three fundamentally different ways to hide ping. Which one you pick is not a matter of taste — it follows from two questions: what is on your wire (state or input) and can you guarantee determinism. Out of that come the authoritative client-server of MMOs and shooters, the rollback of fighting games and the deterministic lockstep of RTS.
🏠 lab~17 min
The gist in 30 seconds
You cannot cheat ping — but you can hide it, and there are exactly three canonical strategies. Authoritative client-server (MMOs, shooters): the server is truth, the client predicts locally and reconciles (see client prediction); we send world state, and the price is traffic ∝ the number of entities plus a permanent fight against cheats. Deterministic lockstep (RTS): we send commands only, and both clients run an identical simulation; traffic is microscopic even at 1500 units, but you get input delay and "everyone waits for the slowest". Rollback (fighting games): we send input only, predict the opponent's input and on a mistake roll back and resimulate frames; your own input is instant, and the price is determinism plus a state save every frame. Choosing a model is choosing what to put on the wire: state is expensive but flexible; input/commands are cheap but demand determinism.

The mechanism: what we put on the wire

The whole taxonomy grows out of one decision. You can send world state over the network ("player A at point X with 80 HP") — then the client needs no determinism, it just draws what it was sent, but the volume grows with the number of entities, and somebody has to be the authority, otherwise a client will lie. Or you send input/commands ("pressed forward", "units 5–40 — attack here") and replay them through an identical simulation on every machine — then traffic is tiny, but any divergence in the math wrecks everything (desync).

The cost of bandwidth

A rough traffic model per player. Broadcasting state, you pay for every visible entity in every snapshot:

Bstate≈ Nent· sent· fsnap

With lockstep/rollback you pay only for commands or input bits, and that does not depend on the number of units:

Bcmd≈ ccmd· scmd· ftick , ccmd≪Nent

This is exactly the thesis of Bettner and Terrano's "1500 Archers on a 28.8" (GDC 2001, Ensemble, Age of Empires): trying to send unit positions capped an RTS at ~250 objects on a 28.8k modem; broadcasting commands on top of a deterministic simulation lifted the ceiling past 1500 — on the wire it is the same handful of commands per turn, even with a thousand archers on screen.

The cost of latency

Hiding ping gives the three models different perceived input latency (how long before you see a reaction to your button). A frame at 60 fps = 16.67 ms; say RTT = 100 ms (one-way ≈ 50 ms ≈ 3 frames).

Lockstep defers your own input by the input delay — enough frames for the command to reach the peer before the shared frame is executed:

dinput= ⌈ tone-wayΔt ⌉ = ⌈50/16.67⌉ =3 frames

That is ~50 ms of lag — and both players feel it, always. Rollback and client prediction give a perceived latency of ≈ 0 (your own input is applied on this very frame), and pay the price elsewhere: by predicting the other side plus rolling back (rollback), or by reconciling with the server (client-server). Naive authority without prediction is the whole RTT, 100 ms — "control by mail".

Perceived input latency · RTT 100 ms · 60 fps 0 50 ms 100 ms naive authority ~100 ms (the whole RTT) lockstep (RTS) ~50 ms input delay client prediction ≈0 + reconcile/rubber-band rollback (fighting) ≈0 + rollback "snap" The green ones pay in resimulation/correction, not lag; red/yellow pay in lag directly.

The three models side by side

PropertyClient-server + lag compLockstep (determ.)Rollback
On the wireworld state (deltas)commandsinput bits
Authoritydedicated servernone (all equal)none (P2P, 2 players)
Determinismnot requiredrequired, strictrequired
Traffic∝ number of entitiestinytiny
Hiding pingprediction + reconcile + interp.input delayinput prediction + rollback
Artifactrubber-banding, "death around the corner"everyone waits for the slowesta visual "snap"
Playersfrom 2 to thousands2–8 (masses of units)usually 2
GenreMMO, BR, shootersRTS, auto-battlersfighting games

The numbers at 100 ms RTT / 60 fps: naive authority — 100 ms of lag; lockstep — 50 ms, but for everyone; client prediction and rollback — ~0 ms of lag, but the first catches a rubber-band whenever it diverges from the server, and the second a 1–3 frame "snap" on a misprediction. Each model gets its own lesson from here: client prediction (ready), rollback in detail.

🕹 Games to play — and what to notice

You cannot feel the three models in one game — each has its own carrier genre. Play three different ones and catch the latency signature of each: what exactly "lags" when the network is bad.

Counter-Strike / any shooter client-server + lag comp

The dedicated server is truth, you predict your own movement and shooting, you see other people slightly in the past (interpolation), and the server rewinds time to resolve hits. The signature of a bad connection is rubber-banding (you get yanked back when the prediction diverges) and "I was already around the corner when I died" (favor-the-shooter).

🎮 Play: in CS type net_graph 3 and play on a high ping. Your own movement rubber-bands and other players teleport — but the world does not freeze as a whole. That is state-on-the-wire with prediction.

StarCraft / Age of Empires deterministic lockstep

Only commands go over the wire, and every machine runs the simulation in sync. So hundreds of units cost nothing in traffic, but your click executes after the input delay (turn N+k), and when somebody lags the whole game freezes, not one unit.

🎮 Play: old StarCraft/AoE on a bad connection — notice that the entire world lags at once (we are waiting for everyone), while units move smoothly and identically on every screen. That is commands-on-the-wire plus determinism. In Korea's PC bangs it went unnoticed: ping was low.

Guilty Gear Strive / Killer Instinct rollback

P2P, 2 players, input bits on the wire. Your own input is instant; the opponent's input is predicted ("they are holding the same thing as last frame"), and on a mistake there is a rollback and a resimulation of a few frames. The signature of a bad connection is a short "teleport snap" of the character, but never input lag.

🎮 Play: in GGST/KI online, catch the micro-"jitter" of the opponent on a ping spike — that is a visible rollback plus resimulation. Compare it with delay netcode (early Smash Ultimate / old SFV): there you get flat input lag on everything instead of a snap. Deeper in the rollback lesson.

EVE Online client-server at the extreme · one shard

The same client-server family, pushed to its limit: a single server (Tranquility), and under overload the server slows time down instead of lagging (Time Dilation) — everything runs at 10–30% speed, but consistently. Authority is preserved at the cost of pace.

🎮 Watch: log into EVE during a major battle (or watch B-R5RB 2014 footage). The TiDi indicator will read "10%" — the world runs in slow motion but does not fall apart. That is choosing "consistency over pace". In detail in "Persistence and sharding".

Deep end · engineering: determinism, floats, and why lockstep is scarier than rollbackskippable

Determinism is the requirement that "identical input → bit-identical result on every machine". Enemy number one is floating point: the same code on different CPUs/compilers gives different results (order of operations, FMA, x87 80-bit vs SSE 64-bit, fast-math). So deterministic engines go fixed-point (integer arithmetic) or pin their floats down hard.

Why lockstep is the harshest

  • Divergence is fatal and silent. In client-server the server will correct the client anyway; in lockstep one divergence in one unit out of thousands → desync, and from there the worlds drift apart irreversibly. You need bit-exact determinism across the whole simulation.
  • Deterministic randomness. A PRNG with a shared seed and a synchronized call order. Any "harmless" rand() outside the synced simulation (particles, sound) must not affect gameplay.
  • Command ordering. Every player's commands for frame N are sorted deterministically (by player id), otherwise A→B and B→A give different results.
  • Checksums. Engines periodically send a hash of the state; if it diverges you catch the desync immediately, not ten minutes later.

Rollback vs lockstep — the shared DNA

Both are deterministic and both send input, but lockstep waits for the input before executing (input delay), while rollback predicts and executes right away, rolling back on a mistake. Rollback = "optimistic lockstep". The price of rollback is a state save every frame (for the rollback); which is why it lives where state is tiny (a fighting game, ~10–50 KB) and is almost inapplicable to an RTS, where state is enormous. See the separate lesson.

Deep end · hosting: dedicated vs P2P, NAT, and where the math happensskippable
  • Who hosts. The client-server of MMOs and shooters requires dedicated servers: anti-cheat, no "host advantage", stability. Lockstep and rollback are usually P2P — there is no authoritative state, so there is nothing to host centrally; cheap, but it falls over when the "host"/peer disconnects.
  • NAT and matchmaking. P2P runs into NAT traversal (STUN/TURN, hole punching); some connections end up going through a relay anyway. Which is why even "P2P" fighting games keep relay servers running.
  • Authority ≠ topology. You can do P2P with one authoritative peer (a listen server, co-op like Helldivers/Deep Rock): cheap, but the host sees the world with no ping and is harder to protect against cheating.
  • Regional servers. You cannot cheat the physics of ping: RTT ≥ 2·distance/c. All three models benefit from a nearby data center — matchmaking pins you to a region to lower the base RTT that all the hiding works on top of.
  • Hybrids. Modern co-op games take client-server with weakened authority (fewer players, a social context, tolerance for lag) — a compromise between the cost of dedicated servers and the protection P2P lacks.
Analogy
Three ways to synchronize a meeting. Client-server is one announcer broadcasting "here is the current picture" to everyone (lots of words, but nobody can lie). Lockstep is an orchestra on one score: the conductor gives only short commands — "bar N+3, come in" — and everyone plays in sync from the sheet music they already have; but the slowest player sets the tempo. Rollback is two synchronized pianists, each guessing their partner's next note and playing immediately; wrong guess, quickly replay the last bar. State is dictated in words; commands/input in notes.
Why it matters
This is the first architectural choice of a networked game, and it is irreversible: the model determines which genre you can even build, your traffic budget, your determinism requirements and how the game feels on a bad connection. Mismatching model and genre (rollback for an MMO, client-server for a fighting game) is the classic expensive mistake. Understanding "what is on the wire → what follows from that" separates "it works on LAN" from "it works with 2000 players in one EVE system".
🔁 Beyond games — where this transfers
This is the fundamental choice in distributed systems: replicate state (state machine replication via a log) or ship state — and where to place authority.

Distributed systems: lockstep = deterministic state-machine replication (Raft/Paxos: we replicate a log of commands, not snapshots; every replica applies the same commands in the same order → the same state). Client-server with snapshots = primary-replica with state shipping. "Send commands, demand determinism" vs "send state, determinism not needed" is exactly this dichotomy.

ML / AI: distributed training is the same fork in the road. Data-parallel = "send state": every worker computes gradients and all-reduce synchronizes weights/gradients (heavy traffic, but the workers are independent). Deterministic reconstruction from a seed = "send commands": store the seed plus the data order and reproduce the epoch bit-for-bit instead of storing checkpoints — cheap on disk, but it demands determinism (like lockstep). And off-policy actors (IMPALA), acting on a stale policy with a later correction, are the "optimistic" path — a relative of rollback.

Backend / databases: replication via an operation log (event sourcing, WAL shipping) vs via a snapshot (snapshot replication) — the "commands or state" choice. Determinism of the replica = reproducibility of the log.

The principle: decide what is cheaper to move — state (flexible, expensive, no determinism needed) or commands (cheap, but everything rests on bit-exact reproducibility). And decide separately who holds authority.

🏠 Lab — a lag and prediction simulator
An interactive lab with no code: move the avatar, dial ping, packet loss and tick rate, switch mode (naive authority / client prediction / lockstep) — and watch with your own eyes how one pays in lag, another in rubber-banding, the third in input delay. Open the lab →
Best moment: at the same ping, switch "naive" → "prediction" — the avatar stops trailing behind; raise packet loss and you will see rubber-band corrections (server and client have diverged). Then turn on "lockstep" — the lag comes back, but flat and without snaps (though it freezes under packet loss).
🔧 Run it and poke at it — on your home machine
What to play by genre is above (🕹). This part is about feeling the difference between the models with tools:
🔧 Poke at it (debug) ~40 min, Godot/GGPO
Take a ready-made networking sample: Godot high-level multiplayer (client-server, MultiplayerSynchronizer) and any rollback plugin (GodotSteam/SnapNet, or GGRS in Rust). In the client-server one, turn on drawing of both the server and the predicted position; in the rollback one, the rollback frames counter and the predicted input. Dial in artificial lag and compare the behavior.
🧪 Test it (with QA eyes) ~15 min
Provoke the signature artifact of each model: rubber-banding and "death around the corner" (client-server, net_fakelag in Source), input delay and "the whole game waits" (a lockstep RTS on a bad connection), a visual "snap" (a rollback fighting game). Checklist: one artifact = one model, do not mix them up.
Checklist: got a client-server and a rollback sample running; saw the rollback counter; matched the three artifacts to the three models.
Connections
foundation
Client prediction — a detailed breakdown of the first model (prediction + reconciliation + lag comp). This lesson is the map, that one is one region of it in depth.
next
Rollback in detail — the third model up close: input prediction, rollback, the frame buffer, delay vs rollback.
next
Persistence and sharding — where the authoritative state lives when there are thousands of players (WoW's shards vs EVE's single shard + TiDi).
Questions worth asking
Why not just send state always — it does not require determinism, after all?
Because of traffic. State grows with the number of entities: an RTS with 1500 units = 1500 positions × the snapshot rate — that fits neither a 28.8k modem (hence "1500 Archers") nor even a modern connection at large scale. Commands/input weigh a few bytes regardless of the unit count. You pay for that in determinism. So RTS historically chose lockstep: a cheap channel matters more than being freed from determinism. And MMOs/shooters chose state because they need authority against cheating and arbitrary content where determinism is unreachable.
If rollback = "optimistic lockstep", why do RTS not use rollback while fighting games do?
Because of the size of the state you have to save every frame for a possible rollback. A fighting game is two characters, ~10–50 KB: serializing and rewinding is cheap. An RTS is thousands of units, megabytes of state: saving every frame plus resimulating several frames on every misprediction would kill both memory and CPU. So RTS put up with input delay (nothing to save or roll back), while fighting games, where the state is tiny and every frame counts, go rollback for zero input lag.
"Everyone waits for the slowest" in lockstep — can you get around it?
Not entirely — it follows from the model. Since frame N+k executes identically for everyone and only after everyone has sent their input for N, one lagging peer holds up all of them. You can soften it: a larger input delay (a buffer against jitter, but more lag for everybody), an adaptive turn delay based on the worst ping, "speed-step" (dynamically stretching the turn duration). Rollback is the radical "we do not wait": predict and roll back. But it does not scale to RTS-sized state (see above).
Why is determinism "scarier" in lockstep than in rollback, if both require it?
The volume of the simulation and the cost of an error. In rollback there are two players and a tiny state — determinism is easier to check and to hold, and a misprediction gets rolled back anyway. In lockstep there are thousands of interacting units, and any divergence in one of them (float operation order, an unsynchronized rand()) → a desync of the whole game with no chance of correction (no authority to fix it). Which is why RTS engines are obsessed with fixed-point, deterministic PRNGs, command ordering and state checksums.
Four-player co-op (Helldivers, Deep Rock) — which model is that?
A hybrid: client-server with weakened authority, often a listen server (one player hosts). There are few players, the context is social (friends, not ranked), lag tolerance is high and cheating matters less → you can skip paying for dedicated servers and strict authority. It is a deliberate choice in the middle of the spectrum: not the full authority of an MMO, not the deterministic P2P of an RTS, but "cheap and good enough". The downside is that it dies if the host leaves.
Further reading