Volter World

Twin declarations start beside the co-located host

Status: Accepted. Date: 2026-10-01. Card t_94bcd252, task t_6e9e0b5f. Amends ADR 0011's ordering of later declarations after the co-located host.

A World that co-locates its twins in one host can still declare a twin as its own process. Dub's planetscale-mysql is one: a MySQL frontend over the planetscale twin's state. The runtime started such a declaration only after the host had published its receipt and every co-located port was admitted. So the frontend's whole process start and readiness sat after the host on every boot.

A co-located twin's address is fixed when its port is allocated, before the host starts. The environment a later declaration consumes, the twin's URL and its templates, is known then. A twin serves: it answers requests and calls no other service while it starts. The planetscale frontend reads its upstream URL from that environment and fetches it per query.

So the runtime records the host's twins and merges their environment as soon as the host is spawned. A later declaration of type twin starts then, beside the host's startup. Any other declaration (an application process, a control-plane service) first waits for the host to be ready, then for every earlier service, as before. up still returns only after the host's receipt and port admission (ADR 0012, ADR 0014) and every declared service's own readiness. A host failure still rolls back every service started so far, including a twin that started beside it.

Measured on Dub's World (32 services), native Node, published runtime 2.0.31 against this branch (with ADR 0014): up took 2.31 and 2.63 s against 1.51, 1.46 and 1.54 s. In the browser tab, probe-instrumented, the time from host admission to the World's env being published was 1.28–5.42 s before and 0.00 s after (the frontend was already ready), in three runs each at load 25–50 (task-evidence/t_94bcd252/f3-diagnostic/final-run/c{0,1,2}-*).

Boundary

The rule rests on a contract of the twin type: a twin declared outside the host may read a co-located twin's address from its environment, but contacts it only to answer a request, never while it starts. The runtime does not check this. A twin that breaks it finds its upstream's port closed while it starts. If that ends its process, up fails, names the service and rolls back. If it retries until the host is ready, it only starts later. Nothing waits silently on a twin that is not serving. A service that must reach a co-located twin while it starts is declared process, with its own command (for a package twin, the package's bin), and starts after the host is ready.

Evidence boundary: the contract was checked for every twin declared outside a host that this work could find. Dub's World has one, planetscale-mysql. Twin's own example Worlds have none. Planetscale's descriptor names it the twin's nativeTransport, the one such frontend in the catalog. Its server listens without contacting its upstream, and it fetches the upstream per query (read in volter-ai/twin's planetscale package; the planetscale pack this repository runs declares no native frontend). That other twin packages do not call another service while they start is extrapolated from the twin role, not checked package by package.

View Markdown source

On this page