0044. Platform services run in resource classes with budgets; the AI gateway, id, PostgreSQL and Caddy come first
Status: accepted, 2026-10-30
Context
The vision asks the whole platform to run on 1 vCPU and 4 GB next to other software. On such a control plane
every service, PostgreSQL, Caddy, Docker and the AI gateway's compression container compete on equal terms: no
unit sets a weight, an OOM score, a memory limit or GOMEMLIMIT; restic and pg_dump run inside xvii-node's own
cgroup; and a gigabyte of swap is in use, part of it the gateway's — the service its owner works through all day.
Manifests can carry memory_max and tasks_max, and none does.
Decision
- Every platform service belongs to a class —
critical, standard or batch — which xvii-node renders as CPU
and IO weights (400, 100, 25), an OOM score (−500, 0, 300) and a default task limit. id and ai are critical;
docs, share, errors, config, tunnel and hooks are batch; the rest standard.
- Every manifest declares a budget:
memory_low (critical only), memory_high, memory_max and tasks_max;
GOMEMLIMIT follows memory_high. Superusers override it per service on an instance. memory_max starts at
twice memory_high, a guard against runaways, and is tightened from what the footprint shows.
- PostgreSQL and Caddy get critical weights, protected memory and low OOM scores through drop-ins xvii-node
writes. The heavy work xvii-node does for others — restic, dumps, restores, builds — runs in transient units
with the lowest weight and a memory ceiling.
- The settings live in drop-ins, so changing a budget is a daemon-reload, not a restart.
- xvii-node reports every unit's memory, pressure events, CPU and tasks and the host's pressure; home shows the
footprint, and analytics alerts on OOM kills, memory pressure and heavy swap.
Consequences
- Under contention the gateway gets sixteen times a batch service's CPU, keeps half a gigabyte under memory
pressure and is the last platform process the kernel kills; batch work slows down instead of pushing it into
swap.
- A service that outgrows its budget is throttled and visible instead of swapping its neighbours out; a budget
set too tight can OOM-kill a service, which is why the ceiling starts high.
- Each service's spec lists its class and budget, and a new service declares them.
- Every service restarts once when the classes first apply. The gateway's compression container gets limits of
its own and is the first thing the kernel kills.
- Design:
superpowers/specs/2026-10-30-autopilot-and-thin-control-plane-design.md in this repository.