Route Commands to multiple services
In this example, we are going to operate two services inside a customer deployment without giving either one a public admin endpoint. An API Worker and an indexer Daemon both expose a status Command; your product selects which service should receive each invocation.
This is the pattern for health checks, diagnostics, synchronization, and other product operations that must execute where the service runs. The result returns to your product, but the customer's network does not accept an inbound connection from it.
Command names only need to be unique within a target resource. This lets related services expose a consistent operation such as status without inventing names such as api-status and indexer-status.
Your product invokes the status Command and names its target. Alien delivers it to either the API Worker or the indexer Daemon in the selected customer deployment.
We will name both resources in alien.ts, register their handlers, and use target() in the calling application to choose one.
Describe both Command receivers
const api = new alien.Worker("api")
.commandsEnabled(true)
.link(index)
.build()
const indexer = new alien.Daemon("indexer-daemon")
.commandsEnabled(true)
.link(index)
.build()A Worker is event-driven compute. A Daemon is a long-running process for continuous work such as indexing or synchronization. Here the Daemon leases its Commands over outbound HTTPS, while the Worker receives Commands through the Alien Worker runtime.
Choose the receiver when you invoke
const client = new CommandsClient({ managerUrl, deploymentId, token })
const apiStatus = await client.target("api").invoke("status", {})
const indexerStatus = await client.target("indexer-daemon").invoke("status", {})The Command name is identical. target() determines which resource receives it.
Run the complete example
cd examples/command-routing-ts
alien dev
ALIEN_MANAGER_URL=<commands url> \
ALIEN_DEPLOYMENT_ID=<deployment id> \
ALIEN_TOKEN=<deployment token> \
bun services/sender/src/index.tsThe sender invokes status twice with different targets. The command name is the same, but the resource named in the request selects the handler.
Read services/api for the Worker, services/indexer for the Daemon receiver, and services/sender for the client.
Deploy both receivers together
alien releasePublishes a version. Nothing is deployed for a customer yet.
alien onboard acme-corpCreates a deployment link for that customer.
The customer opens the link and deploys into their environment.
Your control plane addresses one customer deployment, then targets api or indexer-daemon for each Command invocation.
What you built
You gave your product a narrow operational interface to two services inside a customer deployment. Neither service needs a public admin port, and adding more services does not require a global namespace of prefixed Command names: the caller selects the deployment, resource, and operation explicitly.
Source: examples/command-routing-ts.