Skip to content

Host design

rebaserHEAD edited this page Oct 17, 2026 · 1 revision

design, published verified 2026-10-16

The design for the host: the one process that builds the server from its configuration, checks that configuration and the database before it listens, and starts and stops everything in order. Step 3's first stage builds it, and Roadmap says how far that has got. Where the process runs and what a public deployment adds are on Server core design.

The idea

In short

The server is one process, NexusTomorrow.Server, with one composition root that builds the gateway's listeners, the owners, the write-behind queue and the command layer. It won't start on a setting it can't use or a database that isn't migrated, and it stops in the reverse of the order it started, so every save that was queued commits.

Why

The harness builds this same host in-process, so the composition the tests drive is the one that runs. A setting checked at start turns a mistake into a refusal to start, not a failure at the first login. And the shutdown order is what keeps saves whole: stop taking work, finish the work already taken, then wait for the database.

Decisions

Locked

One composition root, shared by the server and the harness. The harness starts the same host with its own settings, on free loopback ports, with a fake clock.

Settings are checked when they're bound, and the host refuses to start on any that fail:

Setting Must be
Persistence:ConnectionString Set
Gateway:UnknownAccountSecret At least 32 bytes, in base64, and the same across restarts
Gateway:WorldPublicAddress An IPv4 address: the world server's address the login server hands the client
The three client ports Different from each other
Realm:Id At most 16,383, because the character list carries it in 14 bits
Realm:Name Set

Migrating is its own step. The host refuses to start while any schema has migrations pending, and NexusTomorrow.Server migrate applies every schema's migrations and exits.

Start-up runs in order: check the migrations, start the write-behind queue, give the realm owner its first block of character ids, start the owners, and only then open the listeners. Nothing listens before what's behind it is running.

Shutdown is orderly: stop accepting connections and close the open ones, drain each owner's message queue, hand every character in the world back to the realm once the map side exists, wait for every queued save to commit, and exit.

Every listener binds to loopback unless it's configured otherwise, as Hosting requires.

The host keeps the clock. No code reads the system clock: the host supplies a TimeProvider, and the harness swaps in a fake one.

The watchdog runs in the host, once a second on the host's clock, and logs an owner that has stopped draining its queue. What counts as stalled is on Owners design.

The local console reads commands from the server's standard input and runs them through the command layer as the console, which holds every permission. It's on by default (Cli:Enabled), and stays off when input is redirected.

Open

  • Nothing in the design.

Rejected

None recorded yet.

Verification status

Claim Basis
The realm id's 14 bits Established from the client: the character list's realm id field
The start-up and shutdown order Designed; held by the host's own tests as it's built

Open questions

Clone this wiki locally