The packet is still late.

That is the first thing to keep honest. Rollback netcode does not make fiber shorter, routers kinder, Wi-Fi cleaner, or the other player closer. The speed of light remains rude. The network still delivers remote input after the local frame wanted to use it.

What changes is the question the game asks.

The old question is:

Can I run this frame yet?

Rollback asks:

What if I run it now, and fix the past if I guessed wrong?

That is speculative execution. The game predicts a missing input, advances the simulation, renders the result, and keeps enough history to repair itself when the real input arrives.

The latency did not disappear. It changed costume.

Waiting Has a Beautiful Proof

The most conservative multiplayer protocol is beautiful in the way a theorem is beautiful. If every machine runs the same deterministic simulation, then the machines do not need to exchange the whole world. They only need to exchange the inputs.

At frame t, every peer waits until it has every player’s input for frame t. Then all peers execute the same code:

state[t + 1] = step(state[t], inputs[t])

If step is deterministic and every peer sees the same inputs[t], the worlds stay identical.

This is the deep trick behind classic lockstep networking. Bettner and Terrano’s Age of Empires paper is still worth reading because it describes the engineering pressure so concretely: thousands of units, eight players, a 28.8 modem target, and an existing single-threaded engine that could not simply ship full world state every update.1

Lockstep is honest. It makes consistency easy to reason about. It also turns network delay into input delay. If the remote input is late, the frame waits. If the game adds a fixed input buffer, local controls wait too. The better the consistency story, the more the player may feel the network in their hands.

For some games, this is acceptable. A strategy game can hide delay behind turns, command queues, or animation. A fighting game has a harsher contract. A jab, block, parry, throw tech, jump cancel, or one-frame link depends on muscle memory. Adding five to eight frames of delay can change the game the player learned offline.

So the protocol needs to commit a useful sin.

Prediction Makes a Useful Lie

Client-side prediction is older than the current rollback discourse. In Bernier’s Half-Life paper, the client sends commands to the server but also simulates local movement immediately, then reconciles against the authoritative server result when it comes back.2

That idea changes the feel of a first-person shooter. The player does not press forward and wait a round trip for the server to acknowledge that walking is allowed. The client moves now. If the server later disagrees, the client is corrected.

The same family of ideas includes interpolation and lag compensation. The shooter client often sees itself in the present and other entities slightly in the past. For hitscan weapons, the server may rewind the world to the shooter’s view time before testing the shot.3 Bernier describes this as stepping back in server time so the command is evaluated against the state the player actually saw.2

These systems are not cheats. They are negotiated illusions.

Rollback netcode applies the same philosophical move to deterministic peer-to-peer games. GGPO’s public explanation is wonderfully direct: in a fully deterministic peer-to-peer engine, the game can proceed with local input while predicting missing remote inputs; when the real inputs arrive, the game compares them with the predictions and re-simulates from the divergence if needed.4 The open-source SDK asks the game to provide the three verbs that make this possible: save state, load state, and execute a frame without rendering.5

That is the whole bargain.

save the past
guess the missing input
run the present
repair the past

The Branch Predictor Is Holding a Controller

The CPU metaphor is imperfect, but useful.

A processor does not always wait to know which way a branch will go. It predicts the branch, speculatively executes instructions, and throws work away if the prediction was wrong. The win is keeping the pipeline full. The cost is a misprediction flush.

Rollback does the same thing with player input.

At frame t, remote input has not arrived. The game predicts it. A common prediction is boring and effective:

remote_input[t] = remote_input[t - 1]

In many games, inputs are locally autocorrelated. If the other player was holding back last frame, they are likely holding back this frame. If they were neutral last frame, neutral is often a better guess than a random button.

Then the real input arrives:

if actual_input[k] != predicted_input[k]:
    load_state(k)
    replace predicted_input[k] with actual_input[k]
    for f in k..current:
        step(state, inputs[f])

If the prediction was right, nobody notices. If it was wrong, the local machine has to make the present consistent with the corrected past. That may mean a small visual pop, a character snapping a little, a whiff becoming a hit, a sound effect needing suppression, or a burst of CPU work to re-simulate several frames inside one render frame.

The protocol has not removed latency. It has converted some of it into prediction risk.

A Four-Second Time Machine

The lab below simulates four seconds of a tiny deterministic two-player game. Only the remote player’s one-dimensional input is uncertain. The local client receives those remote inputs after a one-way network delay derived from RTT and jitter.

Two policies are compared:

  1. Input-delay lockstep: wait long enough for the remote input before executing the frame. If the buffer is too short, the frame stalls.
  2. Rollback: apply local input after the chosen buffer, predict any missing remote input, save history, and re-simulate when a late input disagrees.

The model is deliberately small. It is not a GGPO implementation, not a fighting game engine, and not a benchmark. It is an executable microscope for the design tradeoff.

The Audit tile is generated by the same JavaScript as the lab. It runs 37,894 assertion-level checks over parameter snapping, replay determinism, input integration, rollback and lockstep ledgers, every rendered frame, delay-curve rows, monotone buffer tradeoffs, volatility, jitter, RTT, rollback-window hard snaps, and re-simulation budget misses. It proves the toy timeline is internally consistent; it does not promise that a commercial game will feel good at those settings.

Rollback correction Predicted remote input Lockstep stall pressure Prediction error True remote state

Deterministic toy model at 60 frames per second. The audit checks simulation contracts. The model covers input timing, prediction, rollback, and re-simulation pressure, not a complete commercial engine or real network stack.

Start with the default. The input buffer is only two frames, about 33 ms. That is far below the round-trip time, so a pure lockstep system would frequently discover that the needed remote input is not available yet. Rollback does not wait. It predicts, occasionally corrects, and keeps local input sharp.

Raise input buffer. The tradeoff panel moves right. Lockstep stalls fall because more packets arrive before their inputs are needed. Rollbacks also fall because the prediction horizon is shorter. The price is immediate: every extra frame of buffer is one more frame between pressing a button and seeing your own character obey.

Raise remote volatility. Last-input prediction gets worse. This is why rollback loves stable input and hates sudden changes. Holding back is easy to predict. A reversal, dash, parry, or button press is exactly the kind of event that matters and exactly the kind of event the predictor did not know.

Raise jitter while keeping RTT fixed. Average latency is not the whole problem. A stable 80 ms can be buffered. A spiky 80 ms forces a choice between larger delay, more rollbacks, or occasional hard correction.

Raise re-sim cost. The visual correction may still be small, but the engine budget becomes fragile. A rollback of six frames means six deterministic updates must fit into the current frame, often alongside the normal update, rendering prep, audio, input, and scripting.

The Engine Must Remember Perfectly

The network code is hard. The game code may be harder.

Rollback wants determinism. Not “usually the same”. Exactly the same. Given the same saved state and the same input stream, the next frame must produce the same state on every peer.

That requirement has teeth:

  1. Random numbers must be seeded and consumed deterministically.
  2. Floating-point behavior must not drift across platforms or compiler settings.
  3. State that affects gameplay must be inside the saved snapshot.
  4. Rendering, particles, camera shake, rumble, and audio cannot blindly fire during speculative frames and then fire again during re-simulation.
  5. Loading an old state must be cheap enough to happen in a frame budget.

This is why rollback is not a library you sprinkle on top at the end. It is a constraint on engine architecture. GGPO can provide the protocol machinery, but the game still has to be written so state can be saved, restored, and advanced deterministically.4

The state boundary becomes a product decision. If a dust particle has no gameplay effect, maybe it should not be rolled back. If a projectile, hurtbox, meter value, cooldown, invulnerability timer, or random seed affects gameplay, it must belong to the deterministic timeline.

The joke version is:

netcode is a serialization format with opinions about time

The serious version is that rollback makes temporal correctness observable.

Fairness Has Several Clocks

Latency compensation often trades one player’s truth against another’s.

In shooters, lag compensation can produce the familiar “shot behind cover” complaint. The shooter aimed at a past version of the target. The server rewound and honored that shot. From the target’s current viewpoint, they had already escaped. Bernier is explicit that this is a game-design tradeoff, not a free lunch.2

Rollback games have a different flavor of unfairness. Your own controls may feel offline, but the opponent can snap into the corrected timeline after their late input arrives. If the rollback window is too small, the game may have to accept a hard correction or desync risk. If the window is large, the repair can be more correct but more visible and more expensive.

The survey literature uses a broad umbrella for these techniques: latency compensation manipulates inputs and/or game states in response to network delay.6 That phrasing is useful because it avoids mythology. The designer is not eliminating latency. The designer is choosing how to manipulate time so the most important part of the experience survives.

Different genres choose differently:

  1. An RTS can prefer deterministic lockstep and command delay.
  2. A shooter can prefer client prediction, interpolation, and server rewind.
  3. A fighting game can prefer rollback because local timing is sacred.
  4. A racing game can use prediction and smoothing because continuous motion can tolerate small spatial error.
  5. A party game may hide inconsistency with generous rules and animation.

The correct protocol is the one whose artifacts fit the game.

Old Names for the Same Bargain

Rollback did not appear from nowhere. Distributed simulation has long had the same shape: delay local execution to reduce inconsistencies, or execute now and repair later.

Mauve, Vogel, Hilt, and Effelsberg describe this tradeoff in terms of local-lag and timewarp for replicated continuous applications.7 Local-lag deliberately reduces responsiveness so operations are more likely to arrive before execution. Timewarp repairs short-term inconsistencies after the fact. The paper’s vocabulary is academic, but the game-feel version is exactly the slider in the lab:

more local lag -> fewer repairs
less local lag -> more repairs

Rollback netcode lives on that frontier.

It becomes attractive when the cost of waiting is worse than the cost of being wrong briefly.

Why Fighting Games Love It

Fighting games are unusually friendly to rollback for several reasons.

The simulation is compact. Two characters, projectiles, timers, hitboxes, meter, stage state, and RNG are much smaller than a giant world full of independent AI and physics objects.

The input stream is small. A direction and a handful of buttons per frame are cheap to send, store, predict, and compare.

The timestep is fixed. Frames are the language of the game. Players already talk about startup, active frames, recovery, links, cancels, and invulnerability in frame units.

The product requirement is brutal and clear. Local timing must feel like offline. If the player’s own jab waits for the network, the illusion fails before the match becomes strategically interesting.

Rollback matches those constraints. It keeps local timing crisp and spends its budget on the opponent’s correction.

But this is also why the technique can be harder in other genres. A large, nondeterministic, physics-heavy, many-player simulation may have too much state to save and too much work to re-simulate. Hidden information can make peer-to- peer input exchange unacceptable. Server authority may be required for cheating, scale, moderation, or economy integrity.

The lesson is not “everything should be GGPO”. The lesson is more general:

interactive systems need a latency budget and a correction budget

Rollback is one particularly elegant way to spend them.

Spend the Latency Budget on Purpose

When an online game feels bad, players say “lag”. That word hides several different failures:

  1. local input latency;
  2. remote entity latency;
  3. prediction error;
  4. correction visibility;
  5. server disagreement;
  6. jitter and packet loss;
  7. CPU spikes during recovery.

Rollback is powerful because it protects the first item. It is dangerous when engineers forget the rest.

The implementation checklist is not glamorous:

  1. fixed timestep;
  2. deterministic gameplay state;
  3. compact snapshots;
  4. replayable input log;
  5. strict separation of gameplay from visual/audio side effects;
  6. resimulation budget;
  7. desync detection;
  8. telemetry for rollback depth, prediction misses, and frame spikes.

That last item matters. Do not only ask whether ping is low. Ask how often the game corrected the past, how many frames it re-simulated, whether players saw the correction, and whether the CPU had room to pay the debt.

The network cannot promise a single present shared by everyone. A real-time game has to manufacture one.

Rollback manufactures it by treating the present as a hypothesis.

  1. Paul Bettner and Mark Terrano, “1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond,” presented at GDC 2001. PDF: zoo.cs.yale.edu/classes/cs538/readings/papers/terrano_1500arch.pdf

  2. Yahn W. Bernier, “Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization,” Valve, GDC 2001. PDF mirror: gamedevs.org/uploads/latency-compensation-in-client-server-protocols.pdf 2 3

  3. Gabriel Gambetta, “Fast-Paced Multiplayer, Part IV: Lag Compensation,” with a concise explanation of client prediction, interpolation, and server-side rewind: gabrielgambetta.com/lag-compensation.html

  4. GGPO official site, “Rollback Networking SDK for Peer-to-Peer Games,” describing deterministic peer-to-peer rollback, input prediction, and re-simulation: ggpo.net 2

  5. Tony Cannon / pond3r, GGPO: Good Game, Peace Out Rollback Network SDK, MIT-licensed source repository: github.com/pond3r/ggpo

  6. Shengmei Liu, Xiaokun Xu, and Mark Claypool, “A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games,” ACM Computing Surveys 54, no. 11S, Article 243, 2022. DOI: 10.1145/3519023. Author page: web.cs.wpi.edu/~claypool/papers/lag-taxonomy

  7. Martin Mauve, Jorg Vogel, Volker Hilt, and Wolfgang Effelsberg, “Local-lag and Timewarp: Providing Consistency for Replicated Continuous Applications,” IEEE Transactions on Multimedia 6, no. 1, 2004. PDF: publications.cs.hhu.de/library/Mauve2004a.pdf