Deployment
Multi-tenant
Many isolated tenant runtimes with scale-to-zero compute and always-on Postgres.
Yoke supports multi-tenant hosted deployments where many customers share one Postgres cluster (tenant_id on every row) while compute scales to zero per idle tenant.
"Serverless" here means compute starts and stops on demand — Postgres stays always on.
Architecture
INGRESS (per tenant)
append API · portal HTTP · webhooks
│
▼
Always-on Postgres
stream · queues · leases
│
▼
TenantSchedulerService
(serverful reconcile loop)
│
▼
SandboxProvider (Docker, Modal, Fly, …)
│
▼
yoke-executor microVM per hot tenant
Rust kernel + libdeno + user package
│
▼
S3 (actor SQLite per tenant prefix)Separation of concerns
| Component | Scales to zero? | Role |
|---|---|---|
| Postgres | No | Durable stream, queues, registry, leases |
| Control plane | No | HTTP API port 8090, tenant ingress |
| Scheduler | No (serverful) | Start/stop decisions on activity |
| Sandbox pool | Yes | 0..N executor containers/VMs |
| Tenant runtime | Yes | Kernel + Deno for one tenant |
Tenant lifecycle
COLD ──(activity)──► STARTING ──(ready)──► HOT ──(idle)──► STOPPING ──► COLD- COLD: No executor. State in Postgres + S3 only.
- STARTING: Scheduler acquired lease; sandbox provisioning.
- HOT: Fan-out, drain, portal HTTP for tenant.
- STOPPING: Flush S3, graceful stop, release lease.
Stop rule: keep tenant container running while pending_events > 0 OR active_dispatch > 0.
Leases
tenant_runtimes table prevents duplicate executors:
- Scheduler CAS on
lease_holder+lease_expires_at - Executor heartbeats every 15s via
YOKE_LEASE_HOLDER - Expired leases → reconciler stops orphan VMs
Activity signals
| Kind | Source |
|---|---|
StreamAppend | After durable stream write |
PortalHttp | Before portal route dispatch |
QueueDepth | Reconciler sees pending rows |
Cron | External tick for portal start() |
Reconcile | Periodic idle sweep |
Sandbox provider trait
| Method | Purpose |
|---|---|
provision(spec) | Create executor VM/container |
destroy(handle) | Tear down |
status(handle) | Running / failed / gone |
DockerSandbox included for local development.
Executor environment
YOKE_TENANT_ID=customer-abc
DATABASE_URL=postgres://... # shared; queries scoped by tenant_id
YOKE_PACKAGE_REF=s3://...
YOKE_STORAGE=s3
YOKE_S3_PREFIX=customer-abcControl plane API
yoke control-plane --database "$DATABASE_URL" --port 8090Headless chat + schedules + tenant ingress proxy. See HTTP API.