Real-Time Backend
Multiplayer Game Networking
One player sees an enemy turning the corner and shoots. The other player has already moved past the corner. Who landed the shot? The answer depends on how the server handles latency, and that is what separates Valorant from lag-riddled indie shooters.
- **Valorant** (Riot Games) runs a server-authoritative model with 128 Hz tick rate and lag compensation of up to 200 ms. The server rebuilds the past world state at the moment of the shot and checks the hit against the target's historical position
- **Overwatch** (Blizzard) applies client prediction to every ability and movement. Reconciliation runs on each server tick (64 Hz). Known case: 'Genji dash' often looked different to different players due to aggressive animation prediction
- **Fortnite** syncs state at 20-30 Hz with delta compression and AoI filtering for 100 players on the map. Building (its unique mechanic) needs a separate higher-priority state channel because it is critical to gameplay
- **Apex Legends** uses its own netcode (Evolution Engine) with client prediction and adaptive tick rate: at high ping update frequency drops, prioritizing accuracy over rate
Client Prediction: a local simulator
At 100 ms latency a player presses 'forward' and the character moves 100 ms later. That is unacceptable. **Client Prediction** fixes it: the client applies inputs locally right away, without waiting for the server. The character moves instantly while the server later confirms or corrects the position.
Valve shipped client prediction in Half-Life/Counter-Strike back in 1999, which made shooters with 100ms+ ping playable. Modern shooters (Valorant, Apex Legends, Overwatch) use the same principle with variations in physics and collision implementation.
Prediction only works for deterministic physics: identical inputs with the same deltaTime produce the same position on client and server. Any non-determinism (float rounding, random without a seed) breaks reconciliation.
Why does the client keep a pendingInputs queue after sending each input to the server?
Server Reconciliation: fixing prediction errors
The client predicts position but the server is the authoritative source of truth. When the server returns an authoritative state (say, another player blocked the path), the client has to correct its prediction. The process is called **server reconciliation**.
Done wrong, reconciliation looks like teleporting: the character snaps backward. The right approach: on ack for tick N the client rewinds to the authoritative position at tick N and replays all unacked inputs (N+1 through current). With deterministic physics the result will match what the server sends in the next update.
In Overwatch reconciliation runs every server tick (64 Hz). The average divergence at 50 ms ping is below 2 pixels. If divergence crosses a threshold (cheating or major desync) the server can force a teleport.
What happens if the client receives a server update with an ackedTick that has already been removed from pendingInputs?
Interpolation: smooth motion for other players
Client prediction applies to the local player. For **other** players there is no input data; the server sends discrete updates 20-64 times per second. Without smoothing the motion looks like teleporting between positions. **Entity Interpolation** smooths it: the client renders a position from the recent past (50-100 ms behind) and interpolates between two known server positions.
Interpolation delay is a deliberate render lag. The Valve Source Engine uses 100 ms by default (cl_interp 0.1). Dropping to 50 ms speeds up display but produces teleports on packet loss. Counter-Strike 2 lets players tune this value.
Why does interpolation deliberately render past state (50-100 ms behind) instead of extrapolating the future?
Game State Synchronization: delta compression and priority
The server cannot send the full game state every tick - too much data. Battlefield 2042 has 128 players per map: the full state covers position, orientation, health, animations, items per player. At 64 Hz that is thousands of objects * 60 fields * 64 times per second.
- **Delta compression**: send only the diffs from the last ACKed state, not a full snapshot
- **Area of Interest (AoI)**: do not send data about players the client cannot see (outside the visibility range)
- **Priority-based updates**: nearby enemies update at 64 Hz, distant ones at 20 Hz, static objects only when they change
- **Bit-packing**: position fits in 24 bits instead of 96 (3x float), rotation angle in 8-16 bits
- **Snapshot history on the server**: enables lag compensation
For fair play the server must send every player the same game state
The server deliberately sends different data to different players (AoI filtering) - it lowers both cheating and traffic
If the client receives every player position, including ones hidden behind walls, wallhack cheats become trivial. Server-side AoI filtering blocks wallhacks and cuts bandwidth by 60-90%. Valve shipped this in CS:GO in 2019 (Trusted Mode + AoI)
What is Area of Interest (AoI) in the context of game state synchronization?
Takeaways
- **Client Prediction** makes local control instantaneous: the client simulates physics immediately and stores input history for later correction
- **Server Reconciliation** removes prediction-vs-authoritative divergence: on server ACK the client rewinds and replays unacked inputs
- **Entity Interpolation** smooths other players' motion with a deliberate 50-100 ms render lag; accuracy beats immediacy for remote positions
Related topics
Multiplayer networking builds on real-time transport and specialized algorithms:
- Game netcode — Next level: tick rate, lag compensation, and rollback netcode as a continuation
- UDP transport — All game netcode sits on top of UDP, so understanding packet loss and jitter is critical
- CRDT structures — An alternative to authoritative-server state sync, used in collaborative tools
Вопросы для размышления
- What happens if physics becomes non-deterministic (say, using float without fixed point)? How does it affect reconciliation?
- How would the architecture change for a game with 1,000 players on one map? Which state-sync optimizations become critical?
- In which situations can client prediction hurt the experience (creating visible artifacts or compromising fairness)?