---
title: "Server authority model"
url: /docs/en-us/projects/server-authority
last_updated: 2026-06-23T22:00:23Z
description: "The server authority model lets you build responsive cheat-free competitive experiences such as FPS, racing, sports, and combat."
---

# Server authority model

In a **server authority model**, the server is the single **source of truth** for the entire experience state, and clients are only trusted to report their own inputs. This architecture is the core netcode foundation of a fair, competitive experience because it prevents entire classes of cheating like flyhacks or speedhacks by never trusting a client to report its own position or state.

## Advantages

In a naive server-owned system, clients would simply send their inputs to the server and display the results of the experience sent back by the server. While technically correct, such a system would face significant **input latency** because every player action would have to travel to the server, be processed, and have the result sent back to the client before it could be displayed. For most experiences, especially those fast‑paced, that round‑trip delay would cause gameplay to feel laggy, unresponsive, and unplayable.

In Roblox's **server authority** model, latency is compensated for by having clients instantly [predict](#client-prediction) the effects of their inputs in addition to sending them to the server. For example, when a player presses a key, the client doesn't wait for the server to respond; instead it **predicts** a few frames ahead of the last known server state. This allows the client to show the result of the input action instantly, effectively hiding network latency and making the experience feel responsive.

Sometimes the client will get its prediction wrong ([misprediction](#client-misprediction)) and, because of network latency, the client will not know that it has made a mistake for a few frames. For example:

> **Warning:** Your client predicts that you've moved forward, but on the server another player used a stun ability that stopped you from moving. The client and server now have different states.

When a misprediction is detected, the client must correct its prediction based on the server's **authoritative state**. If the authoritative state is different from the client's predicted state, the client must [roll back and resimulate](#rollback-and-resimulation) its predicted frames. This system of client‑side prediction, rollback, and resimulation is known as "latency compensation" and helps make server‑authoritative multiplayer experiences feel smooth and responsive.

> **Info:** Mispredictions are a **normal and expected** part of the server authority architecture because clients inherently cannot predict other players' inputs, so actions by other players will always trigger some amount of misprediction. When tuned correctly, the resulting corrections are small and should be imperceptible to players. Read further on [advanced techniques](/docs/en-us/projects/techniques.md) to smooth out and mask network artifacts.
## Setup

As the server authority model requires certain other engine technologies to function correctly, you must first set the following properties on the `Class.Workspace` object in the [Explorer](/docs/en-us/studio/explorer.md):

1. `Class.Workspace.NextGenerationReplication` must be enabled
2. `Class.Workspace.PlayerScriptsUseInputActionSystem` must be enabled
3. `Class.Workspace.SignalBehavior` must be `Enum.SignalBehavior.Deferred|Deferred`
4. `Class.Workspace.UseFixedSimulation` must be enabled
5. `Class.Workspace.StreamingEnabled` must be enabled
6. `Class.Workspace.AuthorityMode` must be `Enum.AuthorityMode.Server|Server` (all of the above must be set first)

## Concepts

The server authority system runs on a few core concepts as follows.

### Client prediction

Through **client prediction**, the client simulates a few frames ahead of the last known server state to predict the effects of player inputs immediately. This hides input latency, but the prediction may later turn out to be incorrect ([client misprediction](#client-misprediction)) and thus require correction. The client tries to simulate just far enough ahead of the last known authoritative server state so that its inputs arrive on the server at the intended frame. The number of frames the client will predict ahead of the known server state is based on the latency behind the client and server.

### Client misprediction

When the client receives the authoritative state from the server, it checks that state against a historical record of what it predicted locally for that frame. When there is a difference between what the client [predicted](#client-prediction) and what the server actually did, this is a **misprediction**. Mispredictions can occur for several reasons, including shifts in network latency, other players acting in ways the client didn't anticipate, the experience running certain logic exclusively on the server, etc.

If the authoritative state is different from the client's predicted state, the client must [roll back and resimulate](#rollback-and-resimulation).

### Rollback and resimulation

When a client detects a [misprediction](#client-misprediction), it must reset to the server's authoritative state and then resimulate to jump back to its predicted frame. Based on the network latency, the client tries to simulate just far enough ahead of the last known authoritative server state so that its inputs arrive on the server at the intended frame.

```mermaid
block-beta
columns 1

    block:Client
        columns 7

        ClientHeader("<span style="color:white;"><b>Client</b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>")
        space:6

        C1["3"]
        C2["4"]
        C3["5"]
        C4["6"]
        C5["<span style="font-size:80%">3 4 5 6</span> 7"]
        C6["8"]
        C7["9"]
    end

    block:Middle
        columns 10

        TimeStart("<span style="color:Grey; font-size:80%;">TIME</span>")
        space:8
        TimeEnd(" ")
        
        space:10
    end

    block:Server
        columns 7

        ServerHeader(["<span style="color:white;"><b>Server</b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>"])
        space:6

        S1["1"]
        S2["2"]
        S3["3"]
        S4["4"]
        S5["5"]
        S6["6"]
        S7["7"]
    end
    
    TimeStart --> TimeEnd
    C1 --"<span style="color:white; background-color:RoyalBlue;">&nbsp; Input (Frame 3) &nbsp;</span>"--> S3
    S3 --"<span style="color:white; background-color:SeaGreen;">&nbsp; Server State (Frame 3) &nbsp;</span>"--> C5

    style Client fill:RoyalBlue
    style ClientHeader stroke-opacity:0, fill-opacity:0

    style Middle fill-opacity:0, stroke-opacity:0
    style TimeStart fill-opacity:75%, stroke-opacity:75%
    style TimeEnd display:none

    style Server fill:SeaGreen
    style ServerHeader stroke-opacity:0, fill-opacity:0
```

_In the above diagram, the client is simulating 2 frames ahead of the server. It sends its inputs for frame 3 which arrive at the intended frame (3) on the server. The server sends the authoritative state for frame 3 and the client receives it on frame 7. The client discovers it mispredicted frame 3 so it resets to the server's frame 3 and resimulates frames 4, 5 and 6 before it simulates frame 7. Players may see a noticeable network artifact such as a sudden movement._

In summary, the **client**:

1. Receives the **authoritative state** from the server and compares it against its own **predicted state**.
2. If the client's prediction was incorrect:
  1. Client rolls back to the last known authoritative state received from the server.
  2. Client resimulates from the authoritative state to its predicted state, re-applying any local inputs.

## Implementation

### Network ownership and prediction

In the server authority model, you're able to keep the core gameplay objects server‑owned without incurring the input latency cost normally associated with server ownership. Things like cars, player characters, or other gameplay‑critical objects can remain server‑owned, even when interacting with other players.

By default, Roblox will automatically predict properties with [simulation access](#simulation-access) near the local player `Class.Player.Character|Character`, but if you want more fine‑grained control, you can explicitly force an instance's prediction on or off with `Class.RunService:SetPredictionMode()`.

### Simulation sync

In the server authority model, the client and the server must both run the core simulation, and the client's simulation needs to be able to [roll back and resimulate](#rollback-and-resimulation) when a [misprediction](#client-misprediction) occurs. To enable this, write your core logic inside functions bound through `Class.RunService:BindToSimulation()` in a `Class.ModuleScript` that's initialized on both the client and server.

![Server authority setup](../../assets/studio/explorer/ReplicatedStorage-Server-Authority.png)

During a resimulation, Roblox will re-run the functions bound to the simulation via `Class.RunService:BindToSimulation()|BindToSimulation()`. Processing player inputs, interacting with synchronized physics objects, and updating the core experience state should live inside those bound functions.

#### Simulation

`Class.ModuleScript` named `Simulation` in `Class.ReplicatedStorage`:

```lua
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")

local Simulation = {}

Simulation.Initialize = function()
	RunService:BindToSimulation(function(deltaTime)
		-- Read player inputs
		-- Update experience state
	end)
end

return Simulation
```

#### ServerLoader

`Class.Script` named `ServerLoader` as child of the `Simulation` `Class.ModuleScript`:

```lua
local Simulation = require(script.Parent)

Simulation:Initialize()
```

#### ClientLoader

`Class.LocalScript` named `ClientLoader` as child of the `Simulation` `Class.ModuleScript`:

```lua
local Simulation = require(script.Parent)

Simulation:Initialize()
```

### State sync with attributes

Roblox automatically synchronizes all properties with [simulation access](#simulation-access) on predicted instances. For custom data, [attributes](/docs/en-us/studio/properties.md#instance-attributes) are the primary way to synchronize instances marked as predicted; on such instances, any mismatch in attribute values between the server's source of truth and the client's prediction will trigger a full [rollback and resimulation](#rollback-and-resimulation).

> **Success:** Use attributes to store experience data that affects your core simulation, including player health, ammunition, inventory, or custom rules (see [limitations](#attribute-limits)).
> **Warning:** Only write to attributes on **predicted** instances from within functions bound through `Class.RunService:BindToSimulation()|BindToSimulation()` to ensure that Roblox can fully track relevant experience states and resimulate properly.
#### Attribute limits

In order to be replicated, an attribute must meet all of the following criteria:

- It is among the first 64 attributes on its `Class.Instance`.
- Its name contains at most 50 characters.
- If a string type attribute, its value contains at most 50 characters.

#### Simulation access

Many properties and methods in the engine API reference include the **Simulation Access** label, for example `Class.BasePart.CFrame`. Properties with this label will be predicted by the server authority system. Additionally, only properties and methods with this label can be accessed inside functions bound with `Class.RunService:BindToSimulation()`.

### Input actions

In a server-authoritative experience, the primary way for a client to affect the experience's state is through the [Input Action System](/docs/en-us/input/input-action-system.md). These inputs are sent to the server and are replayed during resimulation on the client. As a result, `Class.InputAction|InputActions` should be used for **all inputs that affect the core simulation** and they should be checked for sanity before they're processed.

> **Warning:** To reiterate, do not use traditional events like `Class.UserInputService.InputBegan` in the core simulation of a server-authoritative experience.

Note that `Class.InputContext|InputContexts` must be a descendent of a `Class.Player` so that the engine knows who has ownership over the `Class.InputContext`. One approach is to add your `Class.InputContext|InputContexts` to a folder under `Class.ReplicatedStorage` and use a `Class.Script` under `Class.ServerScriptService` to clone the `Class.InputContext|InputContexts` per player:

```lua
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local InputsFolder = ReplicatedStorage:WaitForChild("Inputs")

local function onPlayerAdded(player)
	local clone = InputsFolder:Clone()
	clone.Parent = player
end

Players.PlayerAdded:Connect(onPlayerAdded)

for _, player in Players:GetPlayers() do
	onPlayerAdded(player)
end
```

Using this pattern, you can read `Class.InputAction|InputActions` for all players in `Class.RunService:BindToSimulation()` on both client and server to receive the same data for a given frame and record the previous frame's input in an [attribute](/docs/en-us/studio/properties.md#instance-attributes), for example to trigger a character run when a `RunAction` input action is triggered.

Note that if you need to write custom data into the [Input Action System](/docs/en-us/input/input-action-system.md), you should use a function connected to `Class.RunService.RenderStepped` or `Class.RunService:BindToRenderStep()`, not `Class.RunService:BindToSimulation()`. Firing an `Class.InputAction` in `Class.RunService:BindToSimulation()|BindToSimulation()` can cause clients to produce incorrect results during a resimulation.

```lua
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")

RunService:BindToRenderStep("CameraInput", Enum.RenderPriority.Last.Value, function()
	-- Send the client camera's forward vector to the server through an InputAction
	local cameraForwardInputAction = Players.LocalPlayer.PlayContext.CameraForward
	local cameraForwardVector = Workspace.CurrentCamera.CFrame.LookVector
	cameraForwardInputAction:Fire(cameraForwardVector)
end)
```

### Remote events

[Remote events](/docs/en-us/scripting/events/remote.md) can still be used within the server authority model to facilitate discrete communication between client and server. For example, servers can use remote events to broadcast data about players scoring points or picking up objects, and clients can use remote events as an alternative API for sending inputs to the server, such as for button presses or tapping objects in the 3D world.

> **Warning:**`Class.RemoteEvent|RemoteEvents` might not be consistently ordered with property and attribute updates over the network. For example, if you change a property before firing a remote event on a client, the server might receive the property change after the remote event. To learn more, see [replication order](/docs/en-us/scripting/attributes.md#replication-order).
### Animations, sounds, and effects

Client-side effects like animations and sounds must be written knowing that the client simulation is merely a prediction of the authoritative server state. `Class.RunService:BindToSimulation()|BindToSimulation()` limits what properties and methods can be called from within bound functions to help guide you in writing only to the synchronized simulation state. Displaying the results of this simulation, triggering effects and sounds, etc. should be done in a separate function connected to `Class.RunService.RenderStepped|RenderStepped` that reads the results of the simulation and triggers the desired effects.

Further guidance around rendering a predicted simulation is covered in the [advanced techniques](/docs/en-us/projects/techniques.md) guide.

## Example projects

In addition to this documentation, the following templates can help you get started:

_Racing_

_Soccer_

_Laser Tag_