Guide
Game client-side prediction and server reconciliation systems explained
Harbor Ridge shipped its tactical shooter beta with a 20 Hz authoritative server and zero client prediction. Every movement command waited for a round-trip before the local avatar moved. On 80 ms ping that felt like steering through molasses; on 120 ms players died around corners they had already cleared. Engineering added naive prediction — move locally immediately, trust the server later — without reconciliation. The result was worse: 47% of sessions logged at least one visible rubber-band event, players clipped through doorframes the server rejected, and support tickets accused the game of “teleport hacking.”
Client-side prediction with server reconciliation is the standard client-server answer: the local client simulates the player’s character ahead of confirmation while the server remains authoritative; when the server’s truth diverges, the client rewinds to the last agreed tick, reapplies confirmed inputs, and smoothly corrects the visual offset. This guide covers input command buffers, what to predict locally, reconciliation rewind, error-correction blending, remote-player interpolation (a separate concern), the Harbor Ridge refactor, a technique decision table versus delay-only and rollback netcode, pitfalls, and a production checklist.
Why prediction exists in client-server games
Network latency is physics. At 100 ms round-trip, a player who waits for server acknowledgment before moving experiences 50 ms of input lag minimum — before render pipeline and display latency stack on top. Competitive shooters target sub-50 ms total perceived lag; delay-only netcode cannot get there on real internet paths.
Client-side prediction applies the local player’s inputs to the simulation immediately on the client. The server still runs the same movement code on its tick schedule and broadcasts authoritative transforms. The client’s job is to stay visually responsive while converging on server truth without jarring snaps. Remote players are not predicted by your client — they are interpolated between past snapshots so you always render them slightly in the past, which trades a few frames of visual delay for smooth motion.
Input command buffers and sequencing
Prediction only works if client and server agree on which inputs happened when. Every player action should become a numbered command:
- Sequence ID — monotonically increasing per client; server rejects or de-duplicates out-of-order replays.
- Client tick stamp — the simulation frame when the input was sampled, not when the packet was sent.
- Payload — movement vector, jump flag, ability ID; keep it compact and deterministic.
- Ack watermark — server replies with the highest sequence it has processed so the client knows which predicted frames are confirmed.
The client maintains a ring buffer of unacknowledged commands. Each local simulation step consumes the next command from that buffer and stores a lightweight snapshot (position, velocity, grounded flag) keyed by sequence ID. When the ack advances, confirmed commands are discarded; everything after the ack remains speculative.
Local prediction: what to simulate ahead
Predict only what the local player directly controls and what must feel instant:
- Movement and rotation — walk, sprint, crouch, jump start.
- Weapon swap and reload start — animation can begin locally; ammo count must reconcile.
- Ability wind-up — telegraph locally; damage application stays server-side.
Do not predict outcomes that affect other players without server sign-off: damage dealt, kills, objective captures, inventory changes, or physics objects you do not own. Predicting a grenade explosion locally before the server confirms creates ghost damage numbers that vanish on reconcile — worse than waiting. For hitscan weapons, use server-side lag compensation rather than client-predicted hits.
Server reconciliation: rewind and replay
When an authoritative snapshot arrives, the client compares the server’s position and state for the local player against what it predicted at the same sequence watermark. If they match within epsilon, nothing happens — the common case on healthy connections.
On mismatch, reconciliation runs:
- Restore the client simulation to the snapshot at the acked sequence (or the server-provided state at that tick).
- Reapply every unacked command from the ring buffer in order, using the same movement code the server runs.
- Compute the delta between the replayed position and the currently rendered position — this is the prediction error.
- Apply error correction (next section) instead of snapping the camera.
The server must run identical movement logic with the same tick rate and fixed timestep. Divergent floating-point order, different collision meshes, or client-only shortcuts (bunny-hop exploits baked into prediction) cause constant reconciliation and feel like permanent rubber-banding.
Error correction: smooth blend vs hard snap
Raw reconciliation teleports the player when errors are applied instantly. Players perceive this as rubber-banding. Production games separate logical state (already replayed to server truth) from visual state (what the camera sees):
- Error vector — difference between rendered and logical position after replay.
- Blend decay — reduce the error vector each frame by a percentage (e.g. 10–15%) or move toward zero over 100–200 ms.
- Hard snap threshold — if error exceeds 2–3 m (wrong spawn, teleport hack), snap immediately; small errors blend.
- Velocity carry — when blending, preserve replayed velocity so corrections do not fight momentum.
Harbor Ridge’s first prediction pass snapped on every 5 cm mismatch; telemetry showed 3.2 visible corrections per minute per player. After switching to exponential error decay with a 1.5 m snap cap, visible rubber-band events dropped from 47% to 9% of sessions while maintaining the same server tick rate.
Remote players: interpolation, not prediction
Your client should never predict enemy positions — you lack their current inputs and mispredictions produce unfair peek scenarios. Instead, render remote entities interpolated between two past snapshots (typically 100–150 ms behind real time). The local player feels instant because of prediction; enemies appear smooth because interpolation hides jitter.
Tuning the interpolation delay is a trade-off: shorter delay feels more reactive but stutters on packet loss; longer delay is buttery but gives distant players extra reaction time in your render. Match the delay to your snapshot send rate and target jitter (often 2–3 snapshot periods).
Harbor Ridge refactor: from snap to blend
The Harbor Ridge netcode refactor shipped four changes together:
- Command buffer with server acks — replaced fire-and-forget UDP input packets; eliminated duplicate-movement from retried packets.
- Shared movement DLL — client and server link the same deterministic movement module; collision mesh IDs validated in CI.
- Reconciliation rewind — replaced “lerp toward server position” which fought active inputs and caused door clipping.
- Exponential error decay — 12% per frame blend with 1.5 m snap cap; debug overlay for designers to see error magnitude.
Post-patch metrics on NA-East matchmaking: median perceived input lag (survey) fell from 6.8 to 3.1 on a 1–10 scale; session abandon rate on 80–120 ms ping cohorts dropped from 22% to 11%, overlapping gains from disconnect recovery shipped the same sprint.
Technique decision table
| Scenario | Prefer prediction + reconciliation | Prefer alternative |
|---|---|---|
| FPS / action client-server | Local movement prediction with server rewind | Delay-only input (unplayable above 60 ms) |
| Fighting game peer-to-peer | Not primary | Rollback netcode with savestates |
| Slow tactical turn-based | Overkill | Server-only with UI animation |
| Large open-world MMO | Predict local mount/vehicle only | Server authority with generous caps |
| Physics sandbox | Predict kinematic player only | Server sim for all dynamic props |
| Mobile on flaky LTE | Prediction + generous blend + input buffer | Aggressive snap reconciliation |
Common pitfalls
- Prediction without reconciliation — local state drifts until violent snaps.
- Divergent simulation code — client and server movement never agree.
- Predicting damage or kills — ghost feedback that reverses on reconcile.
- Predicting remote players — unfair peek and stutter on correction.
- Instant error application — constant visible rubber-banding.
- No sequence IDs — retried packets double-move players.
- Ignoring tick-rate mismatch — client at 144 fps, server at 20 Hz without sub-step sampling.
Production checklist
- Assign monotonic sequence IDs to every client input command.
- Buffer unacked commands with per-tick state snapshots for rewind.
- Share movement logic between client and server builds; CI diff test.
- Reconcile by replaying unacked inputs, not by lerping toward server position.
- Separate logical state from visual state; blend prediction error over 100–200 ms.
- Hard-snap only above a distance threshold or on teleport events.
- Interpolate remote entities; never predict enemy positions.
- Keep damage, objectives, and inventory server-authoritative.
- Instrument error magnitude, reconcile rate, and blend duration per session.
- Load-test with 2–5% synthetic packet loss and 80–150 ms latency.
Key takeaways
- Prediction makes local movement feel instant; the server still owns truth.
- Reconciliation rewinds to the last ack and replays unconfirmed inputs.
- Error blending hides small corrections; snaps are for large desync only.
- Remote players are interpolated, not predicted.
- Harbor Ridge cut visible rubber-banding from 47% to 9% with sequenced inputs, shared movement code, and exponential error decay.
Related reading
- Game rollback netcode systems explained — peer-to-peer resimulation for frame-perfect genres
- Game hit registration and lag compensation systems explained — server-side rewind for hitscan fairness
- Game input lag and display latency systems explained — end-to-end latency budget beyond netcode
- Game reconnect and disconnect recovery systems explained — mid-match rejoin after connection loss