Game State Synchronization: What the Backend Owns


Client, relay, match, or backend: who should hold each piece of game state in a live multiplayer game.
Game state synchronization is how a multiplayer game keeps every player’s copy of the game consistent with one authoritative version: who is in the match, where everything is, what each player owns, and what happened last. The hard part is not sending updates. It is deciding which machine owns each piece of state, because the owner is the one whose answer wins when two copies disagree.
For most live games the split is short. The client owns what the player sees right now. A match server or relay owns the live session while it runs. The persistent game backend owns everything that has to outlive the session: accounts, inventory, currency, rank, and progress. Get that split wrong and you get duplicated items, lost progress, and economies that cheaters can print money into.
If you are still choosing between peer to peer, relay, and dedicated servers, start with which multiplayer architecture fits a live game. For the latency side (prediction, interpolation, reconciliation), the game networking tutorial covers it. This Guide stays on state: what kinds exist, where each one lives, and what the backend must own no matter which network model you pick.
What is game state synchronization?
Game state synchronization is how a multiplayer game keeps every player’s copy of the game consistent with one authoritative version, within a latency budget the game can tolerate. It covers three kinds of state, and each kind has a different lifetime and a different natural owner.
There are two broad ways to keep those copies aligned. Deterministic lockstep sends only player inputs and has every machine run the same simulation, which only works if the simulation is perfectly deterministic. State-based sync sends inputs plus the state of the objects that matter, so clients stay aligned without perfect determinism. Glenn Fiedler’s write-up on state synchronization walks through that trade-off. Either way, one machine has to own the result, and the rest of this Guide is about which one.
| State type | Lifetime | Examples | Natural owner |
|---|---|---|---|
| Frame state | Milliseconds to seconds | Predicted position, animation, camera, local effects | The client |
| Match state | One session | Positions, health, score, turn order, who is in the match | The match host: an authoritative server, or a host client on a relay |
| Persistent state | Weeks to years | Account, inventory, currency, progression, rank, friends | The game backend |
Most sync bugs come from blurring these rows. A client that keeps its own copy of currency is treating persistent state like frame state. A match that writes ranked results only into memory is treating persistent state like match state. The fix in both cases is the same: move the state to the layer whose lifetime matches it, and make that layer the single writer.
Where game state lives: client, relay, match, and backend
A live multiplayer game usually runs four layers at once. Each one holds a slice of state at a different trust level, and only the persistent backend is reachable by every client, match, and support tool.
| Layer | What it holds | Trust | Survives a disconnect? |
|---|---|---|---|
| Client | Rendered and predicted state, local input | Untrusted | Yes, while the client process remains alive; not authoritative |
| Relay | Who is connected to the session, and the messages passing through | Neutral: forwards without inspecting | The session survives while other players remain connected; the disconnected presence is removed |
| Authoritative match | Canonical match state, validated every tick | Trusted | Yes, while the match continues; surviving server process loss requires persistence |
| Persistent game backend | Accounts, storage, wallets, leaderboards, social graph | Trusted | Yes, it lives in the database |
The client is fast and close to the player, which is why it predicts, and it is the one layer you cannot trust. A relay forwards messages between clients and fixes connectivity, but it does not run your game rules. The next section covers what that means for state.
An authoritative match runs your game loop on the server. Clients send input, the server validates it, updates canonical match state on each tick, and broadcasts the result. This is server authoritative multiplayer, and it is the right owner for match state whenever cheating or fairness matters.
Match traffic usually runs over a persistent connection, which is why a websocket game server (or rUDP for twitchier games) sits in front of the match, while persistent state can use ordinary request APIs.

Do you still need a backend if you have a relay?
Yes. A relay solves the network problem, not the state problem. It moves packets between players. It does not decide what is true, and it does not remember anything once the session ends.
Look at what a relay actually keeps. In Nakama’s relayed multiplayer, for example, the only match data the server maintains is the match ID and the list of presences. Messages are forwarded without inspection, so there is no cheat detection or error correction, and one client acts as host to arbitrate. Relayed matches live in memory and disappear when the last player leaves. That is by design: a relay is a fire-and-forget pipe.
A relay-only game still has to answer every persistent question somewhere else. Where does the player’s inventory live when they switch phones? Who decides whether a purchase granted 500 gems or 5,000? Where is the season leaderboard? If the answer is “on the host client”, then whoever controls that device controls the answer. That is fine for a casual co-op session with nothing at stake, and not fine for anything players can trade, rank, or pay for. So the working pattern is a relay or authoritative match for the live session, plus a persistent game backend for everything else.
What state should a game backend own?
The game backend should own any state that outlives a session, has economic value, is shared between players, or must survive the loss of a device. A simple test: if a modified client could change it, would that hurt other players or your revenue? If yes, the backend owns it, and clients only ask the backend to change it.
In practice that means the backend owns:
- Identity and accounts. Who the player is across devices and platforms. Every other piece of persistent state hangs off this ID.
- Inventory, currency, and wallets. Anything a player can spend, earn, or trade. Clients request a change and the server decides whether it is valid.
- Progression and saves. Levels, unlocks, quest progress, and cloud saves, so a lost phone does not mean a lost account.
- Competitive results. Ranks, leaderboard scores, and match outcomes that feed matchmaking.
- Shared social state. Friends, groups, and presence that other players read.
- The matchmaking pool. Matchmaking has to see every waiting player, so it cannot live on any single client.
Ownership also means controlling who writes. Good backends enforce it in the data layer, not just in client code:
- Server-only writes for value. In Nakama, wallet updates are only possible from server runtime code, and an authoritative leaderboard rejects scores submitted directly by clients. Storage objects can be marked so no client can write them while the server still can.
- Owner-scoped permissions. Player data that the client may edit, like settings, is readable and writable only by its owner.
- Conditional writes. When two writers race, a version check rejects the stale write instead of silently overwriting. Nakama’s storage engine returns a version with each write so the next write can prove it saw the latest value.
None of this is exotic. It is the difference between a backend that stores data and one that owns authoritative game state and protects it.
The handoff from match state to persistent state
The riskiest moment in game state synchronization is the handoff, when temporary match state becomes permanent player state. A match ends, a turn completes, or a dedicated server shuts down, and the result has to land in the backend exactly once.
Each multiplayer model handles this differently:
- Realtime authoritative matches hold canonical state in memory on one server node for the life of the match. When the match ends, server code writes results, rewards, and rank changes to the backend before the match terminates.
- Turn-based and async matches persist after every turn. The server validates the move, stores the new state in the database, notifies anyone connected, and can stop the match loop until the next turn arrives.
- Session-based matches on dedicated servers (for example headless Unity or Unreal instances) run the simulation elsewhere, so the backend handles matchmaking into the fleet and records results, stats, and progression when the session reports back.
- Relayed matches have no trusted writer at the end. If the result matters, a server must validate it before it is stored, not the host client.
Two rules make the handoff safe. First, only the trusted layer writes the result: the authoritative match, the session server through a server-side call, or a server function that validates a client claim. Second, make reward writes idempotent: key each grant to the match ID and player ID, and reject a second write with the same key, so a retry after a dropped connection does not grant the same reward twice.
Reconnection is the other side of the handoff. Presence and status are per-connection and clear on disconnect, so a returning client re-announces itself and rebuilds from the match and the backend, not from its own cache.
A concrete case: a ranked 1v1 ends while one player’s phone drops signal on the subway. The authoritative match already holds the final score, so it writes the result, rank change, and reward under the match ID before terminating. When that player reconnects ten minutes later, the client reads their new rank from the backend instead of replaying its cached match screen, and a retried reward call is rejected because the key already exists.
Common failure modes when ownership is wrong
Most live incidents around state trace back to one of these patterns:
| Symptom | Root cause | Fix |
|---|---|---|
| Duplicated items or currency | Client or host client writes economy state | Move wallet and inventory writes server-side |
| Progress lost after a crash or device switch | Persistent state only cached on the device | Store progress in the backend and treat the device copy as a cache |
| Leaderboards full of impossible scores | Clients submit scores directly | Submit scores from server code after the result is validated |
| Rewards granted twice | Non-idempotent writes retried after a timeout | Idempotency key or claimed marker recorded atomically with the grant; version checks for concurrent writes |
| Matches that “forget” the result | Host client left before results were saved | Write results from a trusted layer before the match ends |
| Friends shown online when they are not | Presence stored as persistent data | Keep presence per-connection and let it clear on disconnect |
For publishers and larger studios running several live titles, these are not just bugs. They turn into support tickets, refund requests, and economy rollbacks at scale. That is why ownership is an architecture decision made early, not a patch after launch.
Where Heroic fits
Nakama is our open-source game backend, and it covers both halves of this picture: the live session and the persistent state behind it.
For the session, Nakama supports relayed multiplayer for trusted-client games, authoritative multiplayer where your match handler runs at a configurable tick rate and validates every message, and session-based multiplayer that coordinates fleets of dedicated servers. Clients connect to Nakama over WebSockets, so the same realtime multiplayer backend carries match traffic and social updates.
For persistent state, Nakama provides accounts, a storage engine with owner permissions and conditional writes, server-only wallets, authoritative leaderboards, tournaments, and the social graph. You write the ownership rules in Go, TypeScript, or Lua on the server, next to the data.
Pixel Flow is a public example. Loom Games runs authentication and player accounts on Nakama, uses Cloud Save to keep player data synced across devices, and builds its two daily competitive events on Nakama’s Tournaments API and Storage Engine with server-side TypeScript. Because that state lives on the backend, switching phones does not cost a player their progress. More than 10 million players have played it.
For publishers and larger studios, the harder question is running that backend in production. Heroic Cloud is the managed path: dedicated resources, multi-region deployment on AWS or GCP, and SOC 2 Type II compliance, with the same open-source Nakama underneath so you can self-host later without a rewrite.
If you are still mapping the rest of the stack, what is a game backend and how to make an online multiplayer game are good next reads.
FAQ
What is game state synchronization?
What state should a game backend own?
Do you still need a backend if you have a relay?
What is the difference between authoritative and relayed game state?
Where should match results be saved?
How do you stop players from duplicating items or currency?
Does a WebSocket give me an authoritative game server on its own?
What is the difference between state synchronization and client-side prediction?
Enterprise game backends
See how studios ship multiplayer at scale without rebuilding infrastructure.
Walk through Nakama and Heroic Cloud: org-level access control and managed ops without rewriting your stack. Book a demo to see it in action.
- SOC 2 Type II certified
- Proven at 2M concurrent users
- Dedicated capacity, no CCU limits
