Append-only revisions
Rollback promotes an older revision as a new one. History is never rewritten, so it can always be read back.
Compose-native deployment
Most platforms deploy one image at a time. Real systems are stacks — an API, a worker, a broker, a database. Navarch takes the whole Compose file as the unit of deployment, with versioned revisions and zero-downtime blue/green across all of it.
Secrets it cannot read. Values are sealed to each node's public key. Plaintext never reaches the control plane or its database.
$ navarch stack push dev/shop/main ./compose.yaml version 7 · digest 98d75411a605 · swappable: api, worker · pinned: cache, db $ navarch deploy --env dev/shop/main/production revision 12 · slot green · placed on dev-node-2 $ navarch wait 4f2c8e1a --for live scheduling → starting → healthy → live traffic moved to revision 12 · revision 11 superseded · no request dropped
Two copies of an API is the mechanism. Two copies of a database is data loss, and two copies of a scheduler is every periodic job firing twice. So each service declares which it is. Navarch never infers it — the author who has not noticed that blue/green changes cardinality is exactly the one an optional field fails to protect.
Duplicated during a rollout. The new revision comes up beside the old, passes its health check, takes traffic — and only then does the old one go away.
Runs once, shared across revisions. Databases, brokers, schedulers — anything whose correctness assumes a single instance, whether or not it writes to disk.
services: api: image: ghcr.io/acme/api:1.4.0 x-composectl: rollout: swap # duplicated during a rollout ingress: { port: 8080 } cache: image: redis:7-alpine command: ["redis-server", "--save", "", "--appendonly", "no"] x-composectl: rollout: pin # mounts nothing, and still must not be doubled # Omitting rollout: is a parse error. There is no default, deliberately.
The deployment table is append-only, so the record of what ran, when, and why it stopped is still there at three in the morning when you need it.
Rollback promotes an older revision as a new one. History is never rewritten, so it can always be read back.
Traffic moves only once the new revision reports healthy. A bad image fails the rollout and leaves the live one untouched.
Encrypted to each node's public key. The control plane stores ciphertext it has no key for; the agent decrypts at container start.
One call creates an ephemeral environment with a generated hostname and inherited secrets. A TTL reaps it — containers, volumes and all.
Scored placement across nodes, with each environment bound to the node holding its durable state so a later revision cannot drift off it.
Container output is fetched on demand and buffered in memory. Application logs carry secrets, so none of it is written down.
The control plane owns placement and writes the desired state. Each node runs a reconciler that converges on it — no cross-node overlay, no shared network, no orchestration cleverness to debug at midnight.
The Compose file is parsed once into a normalized spec with a stable digest. An unchanged stack does not manufacture a new version.
Every unsupported directive is rejected loudly, all of them in one pass, so you fix the whole file at once rather than one error per attempt.
The scheduler scores the fleet and writes the containers one node should be running.
That node's agent brings the revision up against its own Docker daemon and reports what happened.
A healthy revision goes live in one transaction. The router repoints, and only then is the old revision torn down.
A stack must never run differently than its author expects. Where Navarch cannot honour something, it says so when you push — not by silently changing what your deployment means.
Each of these is a position with a reason behind it, written down — not a gap for you to find in production.