Mirror Networking vs Backend: What Mirror Does (and Doesn't)
Mirror owns Unity client/server networking, RPCs and state sync. A backend owns durable identity, data, economy, leaderboards, discovery and operations.
Quick verdict: Mirror and a managed game backend are normally complementary. Mirror is the realtime Unity networking layer. A backend becomes relevant when state must survive the process, identity must survive the device, or trusted services outside the match need to make durable decisions.
Mirror is a Unity client/server networking framework. It gives you host/server/client modes, pluggable transports, network identities and behaviours, Commands, RPCs, synchronized state, spawning and scene management. It can run a dedicated server or a player-hosted listen server. It does not turn those processes into an account system, persistence service or server fleet.
What Mirror actually gives you
| Capability | Mirror's job |
|---|---|
| Client/server runtime | StartClient, StartServer and StartHost plus server/headless operation through NetworkManager. |
| Transport abstraction | KCP is the current default; other transports cover TCP, WebGL, Steam and other environments. |
| Replicated game objects | NetworkIdentity, NetworkBehaviour, SyncVars/transforms, spawning and interest/visibility systems. |
| Remote actions | Client Commands execute on the server; ClientRpc/TargetRpc calls execute on clients. |
| Server-authoritative patterns | Mirror defaults many synchronization paths to server authority and gives the server the place to validate client requests. |
| Connection authentication hook | NetworkAuthenticator lets you run a custom pre-connect credential/admission exchange before accepting a connection. |
| Local discovery | Network Discovery can find servers on the same LAN via UDP broadcast. |
That is substantially more than “transport-level multiplayer.” Mirror is the realtime networking framework. The missing layer is the hosted/durable control plane around the match.
What Mirror deliberately leaves to you or another service
- Durable player accounts: Mirror exposes authenticator hooks and examples, but it does not operate your identity database, account linking, password reset or OAuth provider configuration.
- Internet matchmaking/discovery: LAN discovery is built in; a global queue, regional discovery service, lobby backend or public server directory is a separate concern.
- Persistent player/world data: SyncVars and network objects describe live session state, not a durable save database.
- Economy and inventory authority: transactional balances, item grants, purchases and replay-safe reward mutations need durable trusted storage/logic.
- Leaderboards and progression: ranking storage and long-lived stats are not a Mirror networking responsibility.
- Live configuration: versioned environment config and rollout policy live outside the networking process unless you build them yourself.
- Fleet lifecycle: Mirror can run in a headless server process; provisioning, placement, capacity, health, draining and termination are separate operations work.
Mirror can be server-authoritative, but your rules still need validation
Calling Mirror “honor-system-ish” is wrong. Commands are sent from clients and run on the server, and authority checks are enforced by default for the sending player/object relationship. Mirror's NetworkTransform is server-authoritative by default unless you change its sync direction.
That does not make arbitrary game logic secure automatically. If a client Command says CmdBuyItem(itemId, clientPrice), the server still has to ignore the client-supplied price and validate ownership, balance, cooldowns and rules from trusted state. Framework authority gives you the place to enforce the rule; it cannot invent the rule for you.
Authentication: Mirror supplies the hook, not the identity provider
Mirror's NetworkAuthenticator is designed for exactly this boundary. Its documentation explicitly lists third-party OAuth/OpenID providers, PlayFab/Steam-like services, device identity and web services as possible identity sources. A custom authenticator exchanges whatever messages your game needs, then calls ServerAccept(conn) only after the server is satisfied.
Also follow Mirror's own encryption warning: do not send reusable secrets over an unencrypted transport just because the authenticator runs before the player object is spawned. Use an encrypted transport or perform sensitive credential exchange over HTTPS.
Architecture A: Mirror + backend you build
Your Mirror host/dedicated process owns realtime simulation. A web/backend service you operate owns accounts and durable state. This gives maximum control, but you also own schema migrations, abuse controls, backups, credential rotation, observability and every new backend feature.
This is a good choice when those backend requirements are themselves part of your product differentiation or your team already operates the necessary systems. There is no honest universal “X engineer-weeks” number: the cost depends on the features and reliability you actually need.
Architecture B: Mirror + managed backend
Mirror still owns realtime networking. A managed backend owns some combination of player auth, durable data, economy, leaderboards, live config or discovery. The cleanest boundary is:
- Authenticate the player before or during Mirror's custom admission flow.
- Attach the verified player identity to the Mirror connection on the server.
- Keep hot simulation state inside the Mirror server instead of round-tripping each frame through HTTP.
- Use trusted server-side credentials for durable mutations such as rewards, inventory changes and final match results.
- Make retries/idempotency explicit at durable boundaries so a timeout cannot award the same result twice.
How Crux fits with Mirror today
Crux's Unity SDK has separate constructors for the two trust boundaries:
// Shipped game client: publishable key, then player login.
var playerCrux = ServerToolkitClient.ForPlayer(
"https://crux.supercraft.host", projectId, environmentId, publishableKey);
var auth = await playerCrux.LoginAnonymousAsync();
Debug.Log(auth.player_id);
// Trusted Mirror dedicated server: server token, never shipped to clients.
var serverCrux = ServerToolkitClient.ForServer(
"https://crux.supercraft.host", projectId, environmentId, serverToken);
var inventory = await serverCrux.GetPlayerDocumentAsync(authPlayerId, "inventory");
await serverCrux.SubmitScoreAsync("season-1", authPlayerId, 1234);
The player-side login gives you a Crux player id and access token for player-scoped API calls. The server-token client gives trusted server code access to server-authorized operations. Keep those credential classes separate.
Do not copy the old “validate Crux JWT locally” recipe
Crux does not expose a player-token JWKS/public key for local verification: player JWTs use HS256, so a Mirror server cannot validate them against a published Crux key. Crux does expose online token validation at GET /v1/auth/me. Present the player token as Bearer auth; a successful response gives the trusted project_id and player_id after the normal expiry, revocation, token-version, ban, organization, and project checks.
For a self-hosted Mirror game, make that admission boundary explicit: your NetworkAuthenticator (or a trusted service it calls) should validate the token through /v1/auth/me, require the expected project, then store the returned player id in NetworkConnection.authenticationData (or your own typed connection state). If your game needs a match-specific replay-resistant admission credential rather than an account token, add your own short-lived match/session ticket on top.
Matchmaking and server discovery are optional add-ons, not Mirror defects
A friend-invite co-op game may only need a join code or platform lobby. A community-server game may need a public registry/browser. A ranked game may need a queue. Do not add all three because a checklist says “multiplayer backend.” Mirror's job begins once you know what endpoint/process the client is joining.
Crux currently has a simple exact game_mode + region pairing matcher and a dedicated-server registry. Those are useful building blocks, but they are not an MMR/party/backfill engine or a fleet orchestrator. Choose them only if that matches the game you are building.
Common integration mistakes
- Using the Basic/Device Authenticator as your account system. They demonstrate the Mirror hook; the Device Authenticator documentation explicitly warns that its device identifier can be spoofed.
- Trusting Command parameters because the Command ran on the server. Server execution is not server validation.
- Putting durable progression only in SyncVars. Live synchronized state disappears with the process unless you persist it deliberately.
- Shipping a backend server token in the Unity client. A modified client can extract it and gain the authority you intended to reserve for trusted code.
- Calling the persistent backend every simulation tick. Keep the hot loop local; write durable facts at deliberate boundaries.
- Assuming Mirror provisions servers. A headless build is not an allocator, scheduler or capacity manager.
Decision rule
Use Mirror alone when local/session-only networking is truly all you need or you already own the surrounding services. Pair Mirror with a backend when identity or state must survive the session, trusted durable mutations matter, or internet discovery/operations are becoming their own subsystem. Replace Mirror only because another netcode model better fits the game, not because you discovered you also need a database.
Related guides
Sources
Technical, pricing, and product claims were checked against these primary sources on the verification date above.