Skip to content

Architecture

Elura separates public client transport from private game execution. A Gateway owns connections and sessions; a World owns business handlers and game state.

text
                 public network                 private network

 Client ── TCP / UDP / WebSocket / WebTransport / QUIC ──> Gateway ── ELR2/TCP ──> World
                                      │   │                     │
                                      │   ├── discovery         ├── handlers
                                      │   ├── session state     ├── middleware
                                      │   └── admission         └── persistence

                                      └── admin HTTP

 Shared infrastructure (optional): Redis, SQL, Kubernetes API, DNS

Gateway responsibilities

The Gateway is the trust and connection boundary. It:

  • accepts TCP, UDP, WebSocket, WebTransport, QUIC, or application-defined client transports;
  • enforces connection, payload, queue, timeout, and rate limits;
  • validates authentication and reconnect tickets;
  • issues and rotates reconnect tickets for authenticated sessions;
  • maintains session state and heartbeats;
  • resolves a World target by region, realm, route, and optional ownership;
  • forwards commands and returns responses;
  • delivers pushes to connected sessions;
  • exposes health, readiness, metrics, diagnostics, and optional admin controls.

Gateways should remain largely stateless when scaled horizontally. Any state that must survive a process or be visible across Gateways—ticket replay, presence, push, session control, admission, and account versions—needs an explicit shared adapter.

The application login service owns credential authentication, account binding, region/realm/player authorization, and scope policy. It may mount HttpAuthApi for access/refresh credentials and one-time Gateway-ticket exchange, or call TicketService::issue_login directly. The live Gateway Session still authenticates only with short-lived, single-use login or reconnect tickets; HTTP access tokens are validated independently on HTTP requests.

World responsibilities

The World is the private business execution boundary. It:

  • accepts authenticated commands from Gateways;
  • validates route IDs and transport metadata;
  • limits connections and in-flight commands;
  • runs middleware and typed handlers;
  • makes identity, trace, session, and push context available to handlers;
  • registers with discovery when a registrar is configured;
  • reports runtime diagnostics through its admin server.

The generated split application uses an internal bearer token. In a production network, combine that token with network policy and, where appropriate, TLS or mTLS.

Realtime gameplay layer

World may host an optional SceneRuntime when multiple players mutate one match, room, or map partition. Each Scene has one bounded mailbox: commands, lifecycle hooks, and ticks execute serially inside that Scene, while different Scenes can run concurrently. Scene placement, distributed ownership, persistence, recovery, and game rules remain application policy.

The gameplay primitives below do not depend on World and can also run in a standalone executor, test, or client-side Rust code:

PrimitiveResponsibility
RoomRoster, readiness, leader succession, and lifecycle state
FixedStepClockBounded deterministic simulation timing
AoiGridTwo-dimensional visibility queries and entered/left deltas
NetcodeTick estimation, redundant input, ACK/reordering, prediction, interpolation, and predicted entity matching
ReplicationPer-observer Spawn, Despawn, delta, keyframe, prediction-key, reorder, and ACK state
LagCompensationHistoryBounded immutable historical snapshots and validated rewind queries
SimulatedLinkDeterministic latency, jitter, loss, duplication, reordering, bandwidth, and queue pressure

An authoritative action-game path normally queues accepted inputs by target Tick, consumes them from a fixed simulation step, updates AOI, records a compact collision snapshot, and emits one replication stream per observer. The client predicts its local entity, reconciles authoritative state, and interpolates remote entities.

Elura owns the bounded protocol and timing machinery. The application owns movement, physics, abilities, AI, entity schemas, serialization, interpolation math, collision queries, hit and damage rules, and client presentation. See Realtime gameplay for the complete composition.

Runtime and application layers

Elura uses dependency inversion at infrastructure boundaries:

Runtime contractExample implementation
WorldDiscoveryDNS, Redis, Kubernetes Endpoints
WorldRegistrarRedis registration
ReplayStoreMemory or Redis
OnlineDirectoryMemory or Redis Session-lease lifecycle
OnlineStatsReaderMemory or Redis online aggregation
OnlineBackendAny Adapter implementing both online contracts
PushTransportIn-process or Redis Streams
SessionControlTransportRedis Streams
AccountVersionStoreMemory, Redis, or SQL
AdmissionControllerRedis admission policy

The application constructs these components explicitly. Gateway-wide services can be grouped with GatewayInfrastructure, while the application-facing Gateway and World types expose fluent methods such as world_discovery, replay_store, push_transport, registrar, route, and middleware. Configuration and duplicate-registration errors are retained by the fluent API and returned by build() or run(). Elura never guesses which adapter or provider to use.

The documentation follows the same boundary: Adapters catalog infrastructure implementations, Providers catalog external business integrations, and Guides explain how to use both without merging their responsibilities.

Monolith versus split runtime

Monolith keeps the same Gateway and World concepts but connects them in-process. This removes private network and discovery concerns and is ideal for local development. A split deployment validates the real connection pooling, timeouts, authentication, discovery, and failure behavior used in production.

Failure boundaries

  • A client protocol error closes or rejects the affected session rather than stopping the process.
  • Handler panics are recovered and counted as World failures.
  • Timeouts and bounded queues prevent unbounded work accumulation.
  • Gateway backend protection can cap concurrent World work and open a circuit after transient failures.
  • Graceful shutdown stops accepting new work and drains existing tasks within configured timeouts.

Released under the MIT License.