naia

May 12, 2026 · View on GitHub

Latest Version API Documentation Book Discord chat MIT/Apache

naia

Server-authoritative entity replication and typed message passing for multiplayer games in Rust, running on native (UDP) and browser (WebRTC).


What naia is

naia lets you define a shared Protocol — a compile-time list of replicated component types, message types, and channel configurations — that both the server and the client agree on. Given that protocol:

  • The server spawns entities, attaches replicated components, assigns users to rooms, and calls send_all_packets every tick. naia diffs changed fields and delivers them to every in-scope client automatically.
  • The client receives entity spawn/update/despawn events and the current server-side field values with no extra bookkeeping.
  • Either side can send typed messages over ordered-reliable, unordered-reliable, or unreliable channels.
  • The server can delegate authority over a specific entity to a client, allowing client mutations to flow back to the server while the server retains final ownership.

naia is ECS-agnostic. Bevy and macroquad adapters are included; the core crate works with any entity type that is Copy + Eq + Hash + Send + Sync.

The internal networking model follows the Tribes 2 Networking Model.


Crate map

CrateRoleAdd as a dependency when…
naia-sharedProtocol definition, component derives, channel typesYou are writing the shared protocol crate
naia-serverCore serverWriting a server without Bevy
naia-clientCore clientWriting a client without Bevy or macroquad
naia-bevy-serverBevy server adapterUsing Bevy on the server
naia-bevy-clientBevy client adapterUsing Bevy on the client

Quick concepts

  • Protocol — the shared type registry. Both server and client build from the same Protocol value; a hash mismatch during the handshake causes rejection.
  • Entity — any Copy + Eq + Hash value your world allocates. naia tracks which entities are replicated and to whom, but never allocates them itself.
  • Room — a coarse membership group. A user and an entity must share a room before replication is possible. Think: match, zone, lobby.
  • Channel — a named transport lane with configurable ordering and reliability. Messages and entity actions travel through channels.
  • Tick — the server's heartbeat. take_tick_events advances the tick counter. TickBuffered channels deliver client input at the correct server tick for prediction and rollback.
  • Authority delegation — a server entity can be marked Delegated, allowing a client to request write authority. The server grants or denies and can revoke at any time.

For the full mental-model guide, see docs/CONCEPTS.md.


Getting started

Core (no ECS)

# shared/Cargo.toml
[dependencies]
naia-shared = "0.24"

# server/Cargo.toml
[dependencies]
naia-server = "0.24"
naia-shared = { path = "../shared" }

# client/Cargo.toml
[dependencies]
naia-client = "0.24"
naia-shared = { path = "../shared" }

See demos/basic/ for a minimal working example.

Bevy adapter

# shared/Cargo.toml
[dependencies]
naia-shared = "0.24"

# server/Cargo.toml
[dependencies]
naia-bevy-server = "0.24"
naia-shared = { path = "../shared" }

# client/Cargo.toml
[dependencies]
naia-bevy-client = "0.24"
naia-shared = { path = "../shared" }

See demos/bevy/ for a complete Bevy demo.

macroquad adapter

# client/Cargo.toml
[dependencies]
naia-macroquad-client = "0.24"
naia-shared = { path = "../shared" }

See demos/macroquad/ for a macroquad demo.


Channel reference

ModeOrderingReliabilityCanonical use
UnorderedUnreliableNoneNoneHigh-frequency telemetry
SequencedUnreliableNewest-winsNonePosition updates (stale ok)
UnorderedReliableNoneGuaranteedOne-off notifications
OrderedReliableFIFOGuaranteedChat, game events
TickBufferedPer-tickGuaranteedClient input for prediction
Bidirectional + ReliableFIFOGuaranteedRequest / response pairs

Platform support

TargetTransportNotes
Linux / macOS / WindowsUDPnaia-socket-native
Browser (wasm32-unknown-unknown)WebRTC data channelEnable wbindgen feature; build with wasm-pack or trunk
iOS / Android (native)Not yet supported — blocked on transport_quic; see FEATURES.md
iOS / Android (via WebView)WebRTC data channelRun the WASM client inside WKWebView (iOS) or Android WebView; same build as the browser target

The server always runs natively. Only the client needs WebRTC support for browser targets.

Steam relay (ISteamNetworkingSockets): Not built-in. The Socket trait is pluggable — a community crate can add Steam networking without modifying naia core.


Coming from another library?

You know…naia equivalentKey difference
renet NetworkedEntity / RenetServerServer<E> + #[derive(Replicate)]naia replicates ECS state automatically (diff + send); renet is message-only
renet send_message / receive_messageserver.send_message::<Ch, M>()naia wraps channels as typed Rust generics
renet ClientIdUserKeySame concept — opaque handle to a connected client
lightyear Replicate component#[derive(Replicate)] on a structnaia is ECS-agnostic; lightyear is Bevy-only
lightyear ComponentRegistryProtocol::add_component::<C>()Same idea; naia uses a builder pattern
lightyear InputChannel / predicted inputTickBuffered channel + receive_tick_buffer_messagesnaia delivers client input at the matching server tick for rollback
lightyear Predicted / Interpolatednot built-innaia supplies the data; you write the prediction/interpolation logic (see PREDICTION.md)
bevy_replicon Replication markerserver.spawn_entity() + #[derive(Replicate)]naia has fine-grained per-user scope control via rooms + UserScopeMut
bevy_replicon visibility filterserver.user_scope_mut(&user) / roomsnaia: rooms = coarse; user-scope = fine-grained