ORCHD

the open-source, self-hosted Fly.io alternative

Run a thousand small apps
on one box.

Hostname routing, per-tenant isolation and scale-to-zero, without the platform bill. ORCHD is a single Go daemon that provisions per-tenant workloads, gives each one a hostname, caps and isolates it, puts it to sleep when nobody is using it, and wakes it on the next request in about a second. No cluster, no control-plane sprawl, no YAML.

~0.9 s
wake from zero
~2.8 s
cold provision
0 MB
RAM while idle
1 binary
control plane + gateway

measured on a Hetzner Cloud VM under gVisor, tinbase workload incl. initdb

the problem

Idle tenants are the expensive ones

Preview environments, per-customer backends, per-project dev servers, agent sandboxes — they all have the same shape: many small workloads, each needing its own URL and its own data, almost all of them idle almost all of the time.

A process manager is too little

systemd or pm2 will keep N processes alive, but nothing hands out hostnames, mints credentials, isolates a tenant from its neighbour, or reclaims the memory of the 900 tenants nobody is using.

Kubernetes is too much

A cluster to run 40 MB dev servers means an API server, etcd, a CNI, an ingress controller and a knative-shaped add-on before the first request is served — and someone to keep all of it alive.

A PaaS is someone else's box

Per-app pricing on a platform you do not operate stops being an option the moment your unit is a free-tier tenant, or the code you run is untrusted, or the margin is the product.

the shape

One daemon, three records

Everything ORCHD does is expressed with a project, a workload and a route. The control plane provisions and mints; the gateway resolves hostnames, wakes what is asleep, and proxies. Both live in the same binary.

                     *.example.com          (wildcard DNS -> the box)
                            |
                     +--------------+   gateway: Host -> route table -> workload,
                     |  gateway     |   wake if suspended, reverse-proxy
                     |  :8081       |   (HTTP, WebSockets, streaming)
                     +--------------+
                            |
        +-------------------+-------------------+
   +----------+        +----------+        +----------+     one instance per
   | workload |        | workload |        | workload |     workload, its own
   | + volume |        | + volume |        | + volume |     volume, suspended
   +----------+        +----------+        +----------+     when idle
                            ^
                     +--------------+   control plane: create projects and
                     |  API :8080   |   workloads, mint keys, attach domains,
                     +--------------+   back up, place in a region
The runtime under the workloads is a swappable driver: host processes locally, Docker + gVisor on a Linux box, microVMs later. Nothing above the driver changes.

Project

grouping

A tenant, an environment, a customer. Owns workloads and cascades on delete.

Workload

the unit

One routable, independently scheduled, scale-to-zero instance with a volume, resource caps and env.

Route

addressing

A hostname pointing at a workload. Default subdomain, custom domains, or a local port.

in practice

A project is one call away

The control plane is an ordinary JSON API behind a bearer key. Everything the admin panel does, you can do with curl — or with a template, which describes a whole multi-workload project in one file that lives in the repo.

provision, then use the endpoint
curl -X POST https://api.example.com/v1/projects \
  -H "Authorization: Bearer $ORCHD_KEY" \
  -d '{"name":"acme","workloads":[{"preset":"vite"},{"preset":"api"}]}'

# -> workloads, each with routes, endpoints and keys.
#    First request through the gateway wakes them.
orchd.json — a template in the repo
{
  "name": "acme",
  "workloads": [
    { "name": "db",  "kind": "tinbase" },
    { "name": "api", "kind": "node", "dir": "api",
      "install": ["npm","install"],
      "run": ["node","index.js"], "port_env": "PORT" },
    { "name": "web", "kind": "static", "dir": "web" }
  ]
}

The same file runs without a control plane at all: npx orchd up boots every workload on your machine, each on its own port. See the CLI.

what you get

Built in, not bolted on

Scale-to-zero + wake

An idle reaper suspends what has not been asked for; the gateway wakes it on the next request. keep_warm pins the ones that must stay hot.

Isolation without KVM

The Docker driver runs tenants under gVisor, a userspace kernel — VM-grade syscall isolation on a plain cloud VM, plus memory, CPU and pid caps per container.

Hostnames and TLS

Default subdomains, bring-your-own domains, path subroutes, and on-demand certificates gated so a cert is only ever issued for a host that resolves to a real workload.

Templates

One orchd.json describes a multi-workload project. Provisioning is async, so a heavy first install never blocks the call.

Versioned images

Freeze a template into an immutable v1, v2… — a tarball plus a container image per workspace — push it to a registry, import it on another instance.

Backups that stay small

Byte-exact volume snapshots to a local dir or S3/R2 over hand-rolled SigV4, excluding everything derived. The control-plane index is backed up too.

Keys, roles, rate limits

A bootstrap key from a file on the box, minted keys stored hashed, readonly vs admin roles, and a per-key token bucket so one client cannot starve another.

Replaceable parts

Runtime driver, state store, backup target, event sink and metrics sink are all interfaces. Most switch from the settings page; the rest are one env var.

Runs on your laptop

The same control loop runs with no Docker at all — workloads as host processes on stable ports, or on a real wildcard *.test domain with trusted TLS.

who uses it

ORCHD is the substrate, not the product

It is a standalone orchestrator with no opinion about what it runs. Two products are being built on it — and they are users of ORCHD, not part of it.

tinbase cloud

hosted backends

One dedicated Supabase-compatible backend per project, coupled the way Supabase Cloud couples them, but a single small process per tenant instead of a container stack.

RapidNative dev environments

per-project runners

A web runner, a mobile runner, an API server and a dev database per generated project — mostly idle, running untrusted user code, which is exactly why the isolation matters.

Start with why it exists

The docs open with the reasoning — the problem, the goals, and the things ORCHD deliberately refuses to do — before any endpoint.

from the same team

Related projects

ORCHD is built by the makers of these open-source tools and products.