Deterministic Netcode Explained: Prediction, Rollback, and Lag Compensation
Online games hide latency with client prediction, deterministic simulation, rollback and lag compensation. A technical explainer on the tradeoffs behind it all.

On this page
Two players press the same button at the same instant. On a couch, the result is immediate and identical. Over the internet, those inputs have to survive a round trip through routers, congestion and physics. Light in fibre takes tens of milliseconds to cross an ocean, and real internet paths add queuing and jitter on top. Every competitive online game is therefore an exercise in deception: making players believe their actions take effect instantly when the truth is still travelling across the network.
Related reading: Epic Games Goes AI-First on Its Delayed Disney Shooter · Google Launches Playground, an AI Platform That Builds Playable Games From Prompts.
This is the story of the tricks behind that illusion (prediction, deterministic simulation, rollback and lag compensation) why each exists, what it costs, and why a fighting game, a real-time strategy game and a shooter solve the same problem in genuinely different ways.
The constraint: latency is unavoidable
A networked game has an authority (usually a server) that decides what is real. A player's input has to reach that authority, be processed, and the resulting state has to come back. That round trip is the ping, and it is never zero.
At 60 frames per second a frame is 16.7 milliseconds. A perfectly ordinary 100 ms ping therefore spans about six frames between pressing a button and seeing the world respond. For a turn-based game that is irrelevant. For a fighting game, where a single frame decides whether a combo connects, or an arena shooter, where a headshot is a matter of degrees, it is the whole problem.
Games attack it from two directions: predict the future and correct later, or delay the local player's input so remote players have time to catch up. Almost every real netcode is a blend of the two.
Client prediction and server reconciliation
The simplest model (send input, wait for the server, draw the result) feels broken. The original Quake worked this way, and players felt every millisecond of it.
The fix, popularised by QuakeWorld and documented by Gabriel Gambetta, is to let the client run the same movement code locally the moment a key is pressed, while the server remains authoritative. The client and server only need to agree closely on the player's own character, so the client predicts that character forward immediately.
When the server's update arrives, it does not simply overwrite the client's world. Instead it says, in effect: here is the authoritative state, and here is the last input sequence number I have processed. The client throws away the inputs the server has already acknowledged, resets to the server's state, then replays the inputs the server has not seen yet.
# Client, every fixed simulation tick
inputs = sample_local_input()
send_to_server(tick, inputs)
buffer[tick] = inputs
state = simulate(state, inputs) # act now, don't wait
# When an authoritative update arrives...
on_server_update(server_state, acked_tick):
state = server_state
for t in range(acked_tick + 1, current_tick + 1):
state = simulate(state, buffer[t]) # replay unacknowledged input
That replay is the essence of server reconciliation. It keeps the player responsive and the server in charge. Corrections are rare (the same deterministic movement code on the same inputs usually agrees) and they are smoothed rather than snapped.
Client prediction works best when an outcome depends mostly on the local player's own input. It cannot predict, for example, being shot by someone the player cannot see; that class of event comes from the server as a correction.
Determinism, fixed-point math and lockstep
A different family of games does not predict at all. It sends only inputs and has every machine run the exact same simulation. If the starting state is identical and the inputs are identical, the results stay identical forever. This is the lockstep model, described in the classic Age of Empires paper "1500 Archers on a 28.8".
Lockstep rests on determinism: for a given game state and a given set of inputs, advancing one tick must produce the same result on every machine.
Floating-point arithmetic (the default in most engines) is IEEE-754 compliant for basic operations but not guaranteed to be bit-for-bit reproducible across different CPUs, compilers, optimisation settings or even debug and release builds. Glenn Fiedler's survey of floating-point determinism collects the war stories: transcendental functions differing between AMD and Intel, engines that pin the FPU precision and rounding mode at startup, and projects that ban floating point from gameplay entirely.
The solid answer is fixed-point math: numbers stored as scaled integers, such as a Q16.16 layout with 16 bits for the whole part and 16 for the fraction. Fixed-point has less range and can be slower than native floats, but it rounds predictably and produces identical results everywhere. Random number generators must be deterministic too, seeded identically and advanced in lockstep so each tick gets the same rolls. Games routinely exchange state checksums to detect a desync the moment it starts.
Determinism is not free, and it is fragile. Any hidden dependence on iteration order, threading, or a third-party physics solver can break it. But it buys something powerful: because only inputs travel, bandwidth stays small even with thousands of units.
Input delay: the simplest honest fix
The most direct way to cope with latency is to wait. Input delay samples the local player's input and holds it for a few frames before simulating, giving remote inputs time to arrive. Input delay is trivially correct and needs no prediction, but the delay is real and the player feels it.
GGPO, the pioneering rollback SDK, treats input delay as a tunable dial rather than a fixed cost. The developer guide suggests choosing the number of delayed frames based on the connection, and warns that a delay which is too short produces longer rollbacks and more visible glitches. Delay and prediction are complements, not rivals.
Why 'fewer delayed frames' is not always better
Every frame of input delay you remove has to be paid for somewhere, usually in longer rollbacks when a prediction turns out wrong. The right setting depends on how much correction a given game can hide.
Rollback: predicting the other player
Rollback netcode is client prediction applied to everyone, not only yourself. Each client immediately simulates the local player's input and guesses the remote player's input based on what they have done recently. It runs the frame right away instead of waiting. When the real remote input finally arrives, the client compares it with the guess. If they match, nothing happens. If they differ, the client rewinds to the last confirmed state, substitutes the correct input, and re-simulates every frame forward to the present, usually in a fraction of a frame, far faster than real time.
The GGPO documentation frames the goal plainly: the design is meant to give players the "illusion of a zero-latency network," so that the timing, reactions and muscle memory built up offline carry over online. The SDK was created in 2009 and popularised rollback in fighting games; its author, Tony Cannon, explained the approach in Game Developer magazine.
Rollback imposes hard engineering requirements on an engine:
- The game simulation must be deterministic and serialisable. You must be able to save and restore the full game state.
- It must be able to step a frame forward without rendering it, because rollback may execute many hidden frames at once.
- Simulation must be separated from presentation, so effects and sounds generated during a rollback can be deferred until the visible frame.
- It must run on a fixed timestep, so a variable tick rate cannot distort the replay.
The Melee community's Slippi project is a well-known demonstration: rollback was retrofitted into a 2001 GameCube game running in an emulator, letting players compete at distance without the input delay that delay-based netplay required.
Rollback is not invisible. If a prediction was wrong, the correction can cause a brief pop or "teleport" on screen. Games tune this with a small amount of input delay and by limiting how far ahead they speculate. In Overwatch, Blizzard's Timothy Ford described predicting even projectiles so rockets feel instant, accepting that a mispredicted rocket occasionally appears to vanish.
Lag compensation: rewinding the server
Shooters usually make the server authoritative and refuse to trust clients, which is good for security but creates a new problem. To smooth out jitter, clients render other players slightly in the past. When you aim and fire at what you see, you are aiming at where the server's world was.
Lag compensation resolves this by having the server rewind the world to the moment the shooter's input was generated. It stores a short history of every player's position and hitboxes, then, on a shot, moves the other players back to where the shooter's client saw them and tests the hit there. This is why lag compensation is often called server-side rewind.
Valve's Source engine popularised the technique, and its documentation and source code show how the server reconstructs an earlier tick within a bounded window. Riot describes the same design for VALORANT: "When the server hears that you've fired a shot, it needs to rewind the world state to what you were looking at when you pulled the trigger in order to accurately determine whether your shot landed," the company explained.
The side effect is real and much argued about. Rewinding favours the shooter, which shapes a genre-wide asymmetry known as peeker's advantage: an attacker rounding a corner can see and shoot a defender before the defender's client has been told the attacker moved. Because the defender's view of the attacker is itself delayed, the aggressive player gets a window of extra reaction time. Games bound the rewind window to stop a player on a very high ping from killing someone who has already moved behind cover, and they tune tick rate and routing to shrink the window rather than eliminate it.
Deterministic lockstep sends only inputs and trusts every machine to reach the same answer. Server-authoritative shooters trust no one and pay for it with a rewound world.
Tick rate and snapshot interpolation
A server's tick rate is how many times per second it advances the simulation. A 64-tick server simulates every 15.6 ms; a 128-tick server every 7.8 ms. Higher rates make hit registration and movement fresher, but the cost is linear: Riot's engineers wrote that running a 128-tick frame within 7.8 ms otherwise consumed an entire CPU core per match, forcing them to optimise down to a budget of a few milliseconds so multiple games could share a host.
Clients rarely simulate the whole world themselves. They receive snapshots of server state and render a smooth approximation. Snapshot interpolation, as Fiedler describes it, buffers incoming snapshots for a short delay and interpolates between the two most recent ones, trading a little added latency for smoothness. The buffer must be deep enough that losing a packet or two does not cause a hitch; Fiedler's rule of thumb is roughly three times the packet interval, then trimmed with a higher send rate. Extrapolation (guessing ahead when a snapshot is late) is used sparingly, because physics and collisions make guesses wrong quickly.
The same tension appears in shooters as command buffering. The server holds a small queue of a client's moves so it can play them smoothly instead of predicting on the client's behalf. Riot documented the balancing act: too little buffering and the server predicts moves and issues corrections, too much and the game feels like high ping. Simulation runs on a fixed timestep decoupled from render frame rate, so a client at 30 fps and a server at 128 Hz still advance the same clock.
P2P, authoritative servers, and why genres diverge
The topology a game chooses shapes everything else.
- Peer-to-peer lockstep (classic RTS): every player sends commands to every other player, and each machine simulates the same world. It needs no dedicated servers and uses very little bandwidth, but it runs only as fast as the slowest player, requires direct connections that firewalls often block, and gives every client the full game state, which makes it easy to cheat by reading information the player should not see.
- Rollback peer-to-peer (fighting games): two players exchange inputs and each simulates both characters locally. A small, fully visible state makes determinism and serialisation tractable, and information leaks matter less when the whole match is already on screen.
- Authoritative client-server (most shooters): one server owns the truth; clients predict only their own actions and render everyone else from server snapshots. It resists cheating, absorbs mismatched hardware, and scales to many players, at the cost of servers, bandwidth and infrastructure.
The security tradeoff
Server authority is the strongest anti-cheat position: a hacked client can lie to itself, but the server's world is what other players experience. That is why competitive shooters centralise authority and are willing to pay for it in latency.
But lag compensation creates its own attack surface. Because the server trusts the client's reported view for hit registration, a player can deliberately induce or fake latency to widen their peeker's advantage, a practice known as lag switching or lag abuse. Bounds on the rewind window and on how much a player's position can be rewound are the standard defence, along with treating asymmetric connections as suspicious.
Deterministic lockstep has a subtler security story. Because every client must reach the same result, any divergence can be detected, and a tampered simulation is caught when its checksum disagrees. That makes it hard to hack the rules. It does nothing to stop information cheating, because the full game state (including enemy positions) is already on the client.
Caveats and open problems
Rollback and prediction are not universal solvents. They demand cheap state serialisation and a simulation that can run many frames faster than real time; a heavy physics simulation with a slow solver may simply be unable to re-simulate quickly enough. Determinism is easy to break accidentally and expensive to maintain across platforms and compilers. Lag compensation trades fairness for feel, and always favours whoever is shooting.
There is also a measurement problem. Players blame "lag" for stutter caused by their own frame rate, by the server, or by jitter, and these have different fixes. Teams increasingly instrument all of it (tick timing, buffer depth, round-trip time and jitter) and expose it to players so the diagnosis is not guesswork.
What to watch
Three trends are likely to keep shaping this field. First, more games are mixing models: server-authoritative simulations with rollback techniques inside them, rather than picking one philosophy. Second, engine support is maturing, with deterministic fixed-point math libraries and rollback tooling becoming available to smaller teams that cannot build netcode from scratch. Third, latency itself is being attacked at the infrastructure layer, through private routing and regional server placement, because the cheapest millisecond is the one that never has to be hidden at all.
The through line is that good netcode is a set of deliberate tradeoffs, not a single algorithm. Prediction buys responsiveness by risking corrections. Determinism buys tiny bandwidth by demanding perfection. Lag compensation buys fair-feeling shots by rewinding time. Understanding which cost a game is willing to pay is the fastest way to understand why it feels the way it does online.








