How do you make a remote player move smoothly between server updates, and where does that smoothing visibly break?
You either buffer snapshots and render the entity slightly in the past so two updates always bracket it, or you dead-reckon forward from its last position and velocity. Interpolation buys smoothness with added latency; extrapolation buys latency with being wrong the instant the entity turns.
What the interviewer is scoring
- Whether interpolation is correctly described as rendering in the past rather than as averaging positions
- That the candidate can state the latency the interpolation buffer adds and where that cost reappears
- Does the candidate recognise dead reckoning as a bandwidth technique and not only a smoothing one
- Whether the failure case is named concretely as a change in direction rather than as general inaccuracy
- Whether they distinguish correcting a position from smoothing towards a corrected position
Answer
Short answer
Dead reckoning predicts a remote entity forward from its last known state, while interpolation renders slightly in the past between two real server snapshots. Interpolation is smoother but adds latency; dead reckoning feels current but visibly breaks when the player turns, stops, or collides before the next update arrives.
Why anything has to be smoothed at all
The server simulates and broadcasts at a fixed rate that is far below the client's frame rate. Take an illustrative 20Hz update rate: a snapshot arrives every 50ms, while the client is drawing every 16.7ms at 60fps or every 7ms at 144fps. If you simply moved each remote entity to whichever position the last packet reported, remote players would advance in visible 50ms hops and would freeze entirely on any dropped or late packet. The client's job between snapshots is therefore to invent plausible intermediate positions, and there are exactly two families of ways to do it: look backwards at data you have, or look forwards past data you do not.
Interpolation renders the world in the past
Interpolation is the safer of the two and the default for player-controlled entities. The client holds incoming snapshots in a buffer and deliberately renders remote entities as they were a fixed interval ago — one snapshot interval plus a margin for jitter, so with 50ms snapshots you might render around 100ms behind the newest packet. Because the render time is always older than the newest snapshot, there are always two real snapshots bracketing it, and the entity's drawn position is a genuine blend of two positions the server actually reported. Nothing is invented; the motion is real, just late.
flowchart TD
A["Snapshots arrive at 20Hz"] --> B["Jitter buffer"]
B --> C["Pick two snapshots<br/>bracketing render time"]
C --> D["Interpolate position<br/>and orientation"]
D --> E["Draw remote entity"]
B -->|"buffer empty"| F["Extrapolate forward<br/>from last snapshot"]
F --> EThe branch worth looking at is the one out of the bottom of the buffer. Interpolation only works while the buffer holds a future snapshot to interpolate towards; the moment a packet is late enough that the buffer runs dry, the client has no choice but to fall into extrapolation, which is why the two techniques are not alternatives so much as a primary and a fallback.
The cost of the buffer is latency you added on purpose. Every remote player is drawn roughly 100ms behind where the server believes them to be, on top of network latency, and that error goes straight into hit registration: when you fire at a running opponent you are aiming at a stale position. Servers resolve this by rewinding — reconstructing where every entity was at the moment the shooter's client claims to have fired — and that rewind has to include the shooter's interpolation delay, not just their ping. Getting that term wrong is a real and common bug, and it shows up as shots that visibly connected being scored as misses.
Dead reckoning projects forward, and also saves bandwidth
Dead reckoning takes the last known position, velocity and orientation and projects them forward with a motion model shared by both ends. The immediate benefit is that there is no buffer and no added latency: the entity is drawn where the model thinks it is right now.
The half of dead reckoning candidates usually omit is that the sender runs the same model. The authoritative side continuously computes what the receivers' projection would currently say, compares it against the entity's true state, and sends an update only when the divergence exceeds a threshold. An entity moving in a straight line at constant speed is therefore almost free on the wire, because the projection stays accurate and no update is needed. This is why the technique came out of large-scale distributed simulation, where the entity count made per-tick snapshots of everything impossible: it is a compression scheme whose smoothing is a side effect.
The threshold is the tuning knob and it is a straight bandwidth-against-accuracy trade. A loose threshold means fewer packets and larger corrections when they come; a tight one means the entity is always nearly right and you have given back the saving.
The direction change is where it always shows
Extrapolation is exactly as accurate as its assumption that motion continues. The instant a player at full sprint reverses, the projection keeps them running forward for the whole window between the reversal and the next update reaching you, so for something like 50 to 150ms every other client is drawing that player somewhere they never were. Then the correction lands and the entity has to get back to the truth, which is visible as a snap or a rubber-band. The same thing happens more sharply against geometry: a player who stops dead at a wall keeps being extrapolated into it, so remote clients briefly draw them standing inside the wall.
This is why the accelerating case is counter-intuitive. Adding an acceleration term to the model reduces error while the acceleration holds and amplifies it when the acceleration changes, because the error now grows with the square of the projection time rather than linearly. A model that is more physically complete is not automatically better; it is better only for motion that obeys it, and player input does not.
Because the correction is unavoidable, the design question is not how to prevent it but how to serve it. Snapping the entity to the corrected position is honest and looks terrible. The usual approach is convergence: keep the entity's position error as a separate quantity and drive it to zero over a short window, so the entity walks towards the truth over a few frames instead of jumping. That is a deliberate decision to render, for a moment, a position that is neither the old estimate nor the new truth — which is acceptable for a distant running player and not acceptable for a projectile, where the position is the gameplay.
The choice per entity type follows from that. Player-controlled entities near you get interpolation, because being slightly late is invisible and being wrong is not. Distant entities, vehicles and anything with smooth predictable motion get dead reckoning with a generous threshold, because the projection is usually right and the bandwidth saving is real. Your own character gets neither, because you predict it locally and reconcile against the server.
Interpolation is late but never invented; extrapolation is current but wrong the moment the entity changes its mind. Pick per entity according to which of those two errors the player can actually see.
© 2026 Preptima. Originally published at preptima.com.
Likely follow-ups
- Why does a second-order dead-reckoning model with acceleration sometimes look worse than a first-order one?
- How does the server's rewind for hit detection have to account for the shooter's interpolation delay?
- What update rate would you pick for a distant entity that a player can see but not interact with, and why?
- A projectile and a walking player need different smoothing. What differs between them?
Related questions
- When would you choose deterministic lockstep over an authoritative server, and what does each model cost you?hardAlso on netcode and state-synchronisation5 min
- Walk me through what rollback netcode does on a single frame, and what it costs to run it.hardAlso on netcode5 min
- How do you optimise UDP packet loss for a high-tickrate competitive shooter?hardAlso on netcode3 min
- A save button calls an API, the request fails, the error appears in the console - and the UI still shows 'Saved'. Walk me through what is actually happening in that promise chain.mediumSame kind of round: concept4 min