Salt & Steel: Server Architecture
Document type: Technical Architecture — Canonical
Status: Canonical
Last updated: 2026-04
See also: Networking Model | Instance Management | Security and Integrity | System Topology
Overview
Salt & Steel requires a server architecture substantially more complex than a standard ARPG because it operates two simultaneous combat worlds — the land domain (islands, dungeons, ports) and the sea domain (open water, naval combat) — that must coexist, interoperate, and transition seamlessly between them. Where Path of Exile's server topology centers on a single instance type (the area instance), Salt & Steel requires two fundamentally distinct instance types running under the same infrastructure, served by the same backend services, and capable of handing players between each other without a loading screen.
The guiding principle is unchanged from PoE's proven model: the server is the sole authoritative truth. The client renders and provides input. The server simulates, validates, and persists. This principle is non-negotiable in Salt & Steel because it covers two combat systems — the GURPS 3d6 resolution on land, and the naval gunnery and positioning system at sea — both of which would be trivially exploitable if any calculation were trusted to the client.
Server-Authoritative Design Philosophy
All gameplay-significant state lives on the server:
- GURPS 3d6 dice rolls are generated server-side using a cryptographically seeded RNG. The client receives the result, not the seed. The bell-curve distribution of 3d6 is sacred — any client-side shortcut would destroy combat integrity.
- Ship positions, headings, sail states, and cannon fire resolution are computed server-side. Client-side ship movement is prediction only, reconciled against server authority.
- Loot generation (item type, modifiers, drop coordinates) is entirely server-side.
- Economy transactions (trade, crafting, currency exchange) are processed server-side before any state change is reflected to clients.
- Crew assignment, crew skill rolls during ship combat, and crew casualty resolution are server-authoritative.
- Weather state is generated and owned by the server; clients receive weather parameters, they do not compute them.
The client's only trusted input is player intent: movement direction, action selection (which skill, which stance, which defense), ship steering commands, and UI interactions. Even the success or failure of a player-initiated active defense (Dodge, Parry, Block) is resolved server-side before the animation result is fed back to the client.
Dual Instance Types
Land Instances
Land instances are the direct analog of PoE's area instances. They host:
- Islands (procedurally generated, party-private)
- Dungeons and sea caves (procedurally generated with hand-crafted landmark rooms)
- Underwater grottos (distinct tileset and physics parameters)
- Boss arenas (fixed layout, party-private, despawned on completion)
- Shipwreck interiors (a subtype with unique flooding mechanics)
Technical characteristics:
| Parameter | Value |
|---|---|
| Server tick rate | 30 Hz minimum, 40 Hz target |
| Maximum concurrent players | 6 (party cap) |
| Instance lifetime (empty) | 10 minutes |
| Instance lifetime (occupied) | Indefinite while players present |
| Procedural seed | Server-generated at creation, stored in instance registry |
| State persistence | Periodic checkpoint to Account Authority every 60 seconds |
Land instances are stateless from an infrastructure perspective. The simulation state lives in server process memory during the instance's active lifetime. On instance expiry or crash, state is lost except for what was checkpointed. Items that a player picked up are persisted to the Account Authority at pickup time (not just at checkpoint), ensuring that loot in-hand is never rolled back by a crash.
Land instances run the full GURPS combat simulation: attribute lookups, stance evaluation, 3d6 roll generation, hit location determination, wound modifier application, active defense resolution, FP deduction. At 30 Hz, each tick must complete all pending combat interactions for all entities in the instance within approximately 33ms. With a party of 6 and a typical encounter of 30-100 monsters, this is feasible on a modern server CPU; boss encounters with complex multi-phase AI require burst budget allocation.
Sea Instances
Sea instances are a novel instance type with no direct PoE equivalent. They are substantially larger, semi-persistent, and support multiple simultaneous ships and their crews as distinct simulated entities operating at two scales simultaneously.
Technical characteristics:
| Parameter | Value |
|---|---|
| Server tick rate | 20 Hz (ship-scale simulation) |
| Combat sub-tick rate | 30 Hz (during active boarding, deck combat) |
| Geographic extent | 4 km × 4 km simulated ocean area |
| Maximum concurrent ships | 16 player ships per instance |
| Maximum concurrent players | 32 (accounting for fleet play) |
| Instance lifetime (no players) | 5 minutes |
| Instance lifetime (occupied) | Up to 4 hours (session cap, then soft migration) |
| Weather state | Owned by Weather Service, injected per-tick |
Sea instances are semi-persistent: unlike land instances which are always private, sea instances are shared. Multiple independent player groups occupy the same sea instance simultaneously, potentially interacting (sight, canon range, boarding) or simply occupying the same ocean zone without interaction. The instance is not party-private; it is region-private (scoped to a specific Nautical Chart zone).
The dual-tick design is the most technically novel aspect of sea instances. At the ship scale (20 Hz), the simulation advances hull positions, heading changes, wind effect calculations, cannon projectile trajectories, and ship component damage. When a boarding action is initiated, the simulation spawns a boarding combat sub-context running at 30 Hz, handling personal-scale GURPS combat between the boarding crew and the defender crew on the target ship's deck geometry. Both scales run concurrently within the same instance process.
Sea Instance State Components:
- Spatial grid: 4 km × 4 km divided into 100m × 100m cells for entity lookup and area-of-interest filtering
- Ship entities: Position (world XY + heading + heel angle), velocity vector, sail state, hull integrity by section (bow/stern/port/starboard/keel), component damage state, crew assignment map
- Projectile registry: Active cannonball/chain shot/grape shot trajectories (position, velocity, remaining lifetime, source cannon, damage parameters)
- Weather state snapshot: Wind vector, wave height, visibility distance, storm intensity, lightning timer
- Sea creature entities: Active creatures, their behavioral state, patrol routes
- Boarding contexts: Active boarding engagements (0-N), each a mini land-instance running on the sea instance's compute budget
- Environmental hazards: Active reef zones, whirlpool positions, volcanic vents
Backend Service Architecture
Game Simulation Servers
The simulation server pool runs both land and sea instance processes. Each physical or virtual simulation server hosts multiple instances (typically 20-60 land instances or 8-16 sea instances per server, depending on memory and compute headroom). Sea instances are compute-heavier than land instances due to dual-scale simulation; they are allocated more resources per instance.
Simulation servers are stateless with respect to persistence. They read initial state from the Account Authority at instance startup and write back at checkpoints and on significant events. The Account Authority, not the simulation server, is the source of truth.
Account Authority Service
The Account Authority is the most critical backend service. It is the canonical persistent store for:
- Character records: Attribute scores, Skill Atlas allocation (every point spent and on which node), advantage/disadvantage list, skill ranks, technique specializations, FP/HP current values at logout, equipment loadout (references, not copies)
- Ship records: Ship class, all component assignments (hull type, sail configuration, cannon loadout by slot, figurehead, crew quarters, cargo hold, special equipment), current hull damage state by section, crew roster assignments
- Item records: Each item as an individual record (base type ID, modifier list with roll values, owner reference, location reference). Items are normalized — they are not duplicated when transferred, only the owner reference changes.
- Cargo/Stash records: Tab structure, item positions within tabs
- Nautical Chart state: Discovered regions, applied modifiers, boss kill flags, atlas-equivalent state
- Reputation scores: Per-faction reputation values for each character
- Voyage Standing: Current Voyage progression state (separate from Account Record permanent state)
- Account Record (permanent, never reset): Captain name history, ship names, reputation summary, Voyage achievements, cosmetic collection
The Account Authority is accessed by simulation servers via an internal gRPC API. The API is not exposed externally. External facing APIs (for community tools, trade sites) access a read-only replica with a separate, rate-limited endpoint.
Trade Service
The Trade Service maintains the Port Marketplace infrastructure:
- Listing index: items listed for sale, searchable by item type, modifier, modifier range, price denomination, region origin
- Transaction processing: atomic transfer of item ownership on trade completion, currency deduction from buyer, currency credit to seller
- Black market routing: separate index for contraband/restricted items, with additional monitoring flags
- Smuggling network state: regional price differentials, available routes (game-world fiction backed by real pricing data)
The Trade Service is a high-read, moderate-write workload. During Voyage launches, listing volume spikes as new Voyage-exclusive items enter the economy. The service maintains a write queue to smooth peak listing bursts without blocking simulation servers.
Authentication and Gateway Service
OAuth 2.1 authentication with PKCE. Session tokens are short-lived (1 hour) with refresh tokens valid for 30 days. All client connections pass through the gateway tier before reaching simulation servers.
The gateway performs:
- DDoS mitigation (volumetric scrubbing, SYN flood protection)
- TLS termination
- Geographic routing (players routed to nearest regional cluster by measured RTT)
- Load balancing within regional cluster
- Connection state tracking for seamless sea-to-land transition handoff (see Instance Management)
Voyage (Seasonal) Management Service
The Voyage Service manages active Voyage state:
- Current Voyage configuration: which mechanic is active, encounter modifiers, weather modifications, exclusive drop table parameters
- Voyage leaderboard: race milestone tracking (first to reach content tiers, boss kills, exploration milestones)
- Voyage Standing rollover: at Voyage end, orchestrates character migration to Legacy layer
- Voyage mechanic injection: pushes mechanic parameters to simulation servers on instance creation
Nautical Chart Service
The Nautical Chart Service manages the endgame progression surface:
- Region discovery state (per-character)
- Region modifier configuration (applied player-side modifiers equivalent to PoE map modifiers)
- Boss kill flags for pinnacle content gating
- Chart region property storage (danger level, faction ownership, weather profile)
- New region reveal on successful exploration
Weather Service
A dedicated simulation running a procedural weather model at the region level:
- Weather state advances on a real-time clock (not game-tick driven) at 1-minute resolution
- Storm fronts have position, heading, and intensity; they propagate across the chart in ways players can observe (storms visible at render distance for 15-30 minutes before arrival)
- Weather state is injected into sea instance ticks; land instances receive simplified weather parameters (rain intensity, visibility modifier, wind speed category)
- Voyage-specific weather overrides (e.g., permanent supernatural fog for a Sargasso Voyage) are injected by the Voyage Service into the Weather Service's output for affected regions
Social and Party Service
- Party formation and management (up to 6 players for land content, fleet coordination channels for naval)
- Crew roster management (shared crew banks for Crew guilds)
- Chat routing: global, trade, party, whisper channels
- PvP matchmaking for naval duels and port arena
Faction Service
- Reputation tracking per character per faction
- Faction territory state (which factions control which chart regions, updated by aggregate player action)
- Elite crew unlock gate checking
- Price modifier lookup for trade service integration
Scalability
Voyage Launch Spike Handling
Voyage launches are the Salt & Steel equivalent of PoE league starts. The concurrent player spike on Voyage day one can reach 5-10× sustained load. The scalability strategy combines pre-provisioning, cloud burst, and queue management.
Login thundering herd mitigation:
- Login queue with real-time position display — players see their estimated wait time, reducing frustration
- Staggered start: Voyage launch has a 15-minute rolling window where login capacity is expanded 50 players at a time, preventing a single-second spike
- Auth service scaled to 10× normal capacity pre-launch (cloud burst)
Instance creation burst:
- Instance process pooling: 500 warm land instance processes pre-allocated on Voyage day. When a player enters a zone, a pre-warmed process is assigned rather than a new process spawned. Cold start time drops from ~3 seconds to ~200ms.
- Sea instance pre-warming: 50 sea instance processes per region pre-allocated
- First-zone funnel detection: all players begin in the same starting region. That region's server capacity is scaled to 5× normal for the first 72 hours.
Database write amplification:
- Account Authority uses a write-ahead log with batch commit. Individual item pickups are written to the log immediately (ensuring loss prevention) but committed to the primary database in batches of 100ms.
- During Voyage start, character creation writes are routed to a Voyage-specific database shard, keeping the main Account Authority write path clear for returning players.
Capacity monitoring:
- Real-time dashboards tracking: login queue depth, instance creation latency (p50/p95/p99), simulation server CPU and memory utilization, Account Authority read/write latency, Trade Service indexing lag
- Automated scaling triggers: if instance creation latency p95 exceeds 5 seconds, auto-scale adds simulation server capacity from cloud burst pool
Instance Scaling and Load Balancing
Land instances are distributed across simulation servers by a scheduler that considers:
- Current CPU utilization of candidate servers
- Memory available (land instance estimate: 150-400 MB per instance)
- Network proximity to the majority of the party members (minimizes internal cluster latency)
- Server affinity for ongoing instances (keep party members on the same physical server cluster to minimize inter-instance communication latency for transition handoffs)
Sea instance assignment additionally considers:
- Existing sea instance density in the target chart region (to enable discovery of other players' ships)
- Sea instance compute budget availability (sea instances are compute-heavier)
- Geographic affinity of existing occupants (avoid assigning a new EU player to an instance predominantly occupied by NA players, which would degrade networking for the majority)
Database Sharding Strategy
Character and ship data is sharded by account ID using consistent hashing. A 256-shard ring with virtual nodes ensures even distribution and smooth rebalancing when shard count changes. Each shard is a PostgreSQL instance with a read replica for Account Authority read traffic.
Item data is sharded by item GUID. Items are independent records with owner references; the sharding key is the item itself, not the owner. This prevents hot spots on high-activity accounts from concentrating item write load on a single shard.
Trade listings use a separate service database with a full-text search index (Elasticsearch cluster) for modifier search. Trade listing data is ephemeral — items listed for trade are replicated to the search index, not stored only there. The canonical item record in the item shard is the authority.
Nautical Chart state is per-character, sharded alongside character data. Chart state changes are low-frequency (discovery events, modifier application) and do not create significant write pressure.
Faction and reputation data is sharded by character ID. Faction territory state (aggregate, not per-character) is stored in a single low-contention database with a read-through cache. Territory state changes are infrequent (update cadence is minutes, not milliseconds).
Regional Server Deployment
Four primary regions with full service stacks:
| Region | Datacenters | Target Population |
|---|---|---|
| North America | Virginia (primary), Oregon (failover) | NA West, NA East, South America |
| Europe | Frankfurt (primary), Amsterdam (failover) | EU, Russia, Middle East, Africa |
| Asia Pacific | Singapore (primary), Tokyo (secondary) | Southeast Asia, East Asia, South Asia |
| Oceania | Sydney (primary) | Australia, New Zealand, Pacific Islands |
Each region runs a full stack: gateway, simulation servers, Account Authority shard replicas, Trade Service (regional inventory), Social Service, Weather Service instance. Account Authority writes always go to the player's home region's primary shard; cross-region reads use eventual consistency replicas.
Cross-region play is supported: a player on the NA region can party with an EU player by selecting a server region explicitly. Both players experience increased latency (the instance runs in one region). The client displays latency warnings when a player is in a non-home region.
Crash Recovery and State Persistence
Instance crash protocol:
- Monitoring detects missed heartbeat or process termination signal within 5 seconds
- Instance removed from instance registry; connected players are disconnected
- Players return to their ship (if sea instance crash) or to port (if land instance crash) — safe harbor semantics
- Items in player inventory at crash time are preserved (inventory checkpointed every 60 seconds and at item pickup)
- Items on the ground at crash time are lost (ground items are instance-local, not persisted to Account Authority)
Safe harbor semantics:
- Sea instance crash: player's ship state (damage, position, cargo) is rolled back to last checkpoint. The ship cannot be destroyed by a crash; it returns to the port it last docked at if the checkpoint predates the sea session.
- Land instance crash: player character HP/FP returns to values at instance entry (safe entry checkpoint). Loot picked up is preserved. XP gained since last checkpoint may be lost.
Rollback policy:
- Individual crashes: no manual item restoration. Players are compensated with a minor currency award if the crash was a verified server-side fault (not a client disconnect).
- Mass outages affecting 1000+ players: evaluated case-by-case. Compensation cosmetics for verifiable session loss. Economy-significant item restoration only for catastrophic and verifiable loss events (analogous to PoE's character ID collision rollback).
Service Dependency Map
┌─────────────────────────────────┐
│ Gateway / DDoS Shield │
└──────────────────┬──────────────┘
│
┌────────────────────────┼────────────────────────┐
│ │ │
┌────────▼────────┐ ┌──────────▼──────────┐ ┌────────▼────────┐
│ Auth Service │ │ Land Instance Pool │ │ Sea Instance Pool│
│ OAuth 2.1 │ │ 30-40 Hz tick │ │ 20 Hz ship tick │
│ Session Mgmt │ │ GURPS simulation │ │ 30 Hz deck combat│
└────────┬────────┘ └──────────┬──────────┘ └────────┬────────┘
│ │ │
└────────────────────────┼────────────────────────┘
│
┌───────────▼───────────┐
│ Account Authority │
│ Character/Ship/Item │
│ gRPC internal API │
└───────────┬───────────┘
│
┌──────────────────────────────┼──────────────────────────────┐
│ │ │
┌───────▼──────┐ ┌─────────▼─────────┐ ┌─────────▼────────┐
│ Trade Service│ │ Nautical Chart │ │ Voyage Service │
│ Port Market │ │ Service │ │ Seasonal State │
│ Black Market │ │ Atlas State │ │ Leaderboard │
└──────────────┘ └───────────────────┘ └──────────────────┘
┌──────────────┐ ┌────────────────────┐ ┌──────────────────────┐
│ Weather Svc │ │ Social/Party Svc │ │ Faction Service │
│ Region state │ │ Crew guilds │ │ Reputation/Territ. │
│ Storm fronts │ │ PvP matchmaking │ │ Price modifiers │
└──────────────┘ └────────────────────┘ └──────────────────────┘
Infrastructure Technology Stack
| Layer | Technology | Rationale |
|---|---|---|
| Simulation servers | C++ custom engine, Linux | Performance-critical; no acceptable GC pauses for combat simulation |
| Backend services | Go | Fast startup, low memory, excellent concurrency for service mesh |
| Account Authority DB | PostgreSQL 16 + read replicas | ACID compliance required for item ownership integrity |
| Trade search index | Elasticsearch | Full-text + range search on modifier values |
| Service mesh | gRPC + Protocol Buffers | Binary protocol, strongly typed, low overhead |
| Cache layer | Redis Cluster | Session tokens, hot account data, instance registry |
| Message queue | Apache Kafka | Voyage event streaming, audit log, economy telemetry |
| Cloud burst | AWS EC2 + Auto Scaling Groups | Voyage launch spike capacity |
| Monitoring | Prometheus + Grafana | Real-time operational dashboards |
| Distributed tracing | OpenTelemetry + Jaeger | Cross-service request tracing for latency diagnosis |
| Container orchestration | Kubernetes (simulation servers as StatefulSets) | Instance lifecycle management |
Cross-references: design/10-technical-architecture/networking-model.md, design/10-technical-architecture/instance-management.md, design/10-technical-architecture/security-and-integrity.md, design/topology/system-topology.md