Why this app is pinned to one replica

The party lives in server memory and every watcher of a room shares it, so two replicas means one URL serving two different parties. railway.json pins numReplicas to 1 as a correctness constraint, not a cost saving.

Horizontal scaling is the reflex, and here it is a bug. Two instances behind one hostname is two simulations: half the audience watches one betrayal and half watches a different one, and neither half can tell.

It is a constraint you buy something with

In exchange for not scaling out, the whole design gets simple. No database, no coordination, no state machine spread over a cache, no sticky sessions. One party in memory, streamed. That is worth more than an axis of scaling this app does not need, and since the cost is flat in the audience, the pressure to add instances never arrives from the bill.

If it ever does need to scale, the answer is a room per process addressed by routing, not replicas behind a load balancer.

Write the constraint down where it is enforced

numReplicas: 1 lives in the deploy config with a comment, the rule is in the repo's own guidance, and the reason is on a page like this one. A single-instance requirement that only exists as a number in a dashboard survives about one incident.

Deploy notes

Git-driven only: push to the default branch and let the trigger deploy. A manual CLI deploy reaches production without being on the branch, so the next automatic deploy reverts it.

One more sharp edge, specific to Railway: the config-as-code path resolves from the repository root, so a monorepo app needs apps/<name>/railway.json even when the service's root directory is already apps/<name>. Getting that wrong kills the deploy in about five seconds with Snapshot code: service config not found.

Read next

More on the build