Adom Blue-Green
Public Made by Adomby adom
Blue-green deploys with zero failed requests for service containers. Proven on Component Ocean.
Install?
Zero-failed-request deploys for any Adom service container: an nginx front door, blue and green slots, a flip only when the new build reports ready at the new commit, and the old slot stopped only after it has served every request it accepted.
adom-wiki pkg install adom/adom-bluegreen
Latest: v0.1.1, published
README
markdownadom-bluegreen
Deploy a service container without failing a single request.
Most of our service containers deploy the same way. A watchdog notices a new commit on main, kills
the process and starts the new one. Everything that calls the service fails until the new process has
warmed up. For Component Ocean that took 60–120 seconds per push. For anything production-dependent
that is not acceptable: the bar is zero failed requests, not a short gap.
adom-bluegreen is the setup that got Component Ocean there, packaged so any service container can use it.
| Component Ocean, live | requests during the deploy | failed |
|---|---|---|
| automatic deploy (cron picked up the push) | 1,372 | 0 |
| manual deploy | 2,365 | 0 |
| kit self-test: deploy under load, plus a refused broken build | 13,368 | 0 |
The idea
public URL ──> :3456 nginx (the front door; it reloads, it never restarts)
├── :3457 blue slot = git worktree at the commit being served
└── :3458 green slot = git worktree at the next commit, warming up
- Warm the new version next to the old one. A new commit starts in the idle slot while the live slot keeps serving.
- Switch only when the new version says it's ready, at the right commit. Each service answers
GET /readywith200 {"ready":true,"git_sha":...,"inflight":n}once it is fully warm. If the new slot never gets there, it is never served, and the old one keeps going. - Switch without closing the door. nginx reloads its config while keeping the listening socket. New requests go to the new slot, and requests already in progress finish on the old one.
- Let the old version finish before it stops. The old slot is stopped only when its
inflightcount has been 0 for 5 seconds, so every request it accepted gets its answer.
Using it on your service
- Add the
/readycontract.examples/has copy-ready versions for Bun, Node and Python: about 15 lines, including an in-flight counter. - Write a small config (
examples/service.conf.example): name, repo, branch, three ports, the start command, and which gitignored paths (such asdata/) both slots share. - Run
scripts/install.sh your.conf. It checks the config, installs nginx and schedules the watchdog. - Prove it: run
scripts/probe.shagainst your service while you push a commit. It must end with0 failed.
Before relying on it on a new container, run tests/selftest.sh. It performs a real deploy of a
throwaway app on spare ports and must report 10 passed, 0 failed.
The full guide, including operating it, rolling back and adopting a port a service already uses, is
in SKILL.md. It installs as a skill, so any Claude or Codex session can set this up for you.
What we learned the hard way
Each item below failed once while this was built. The kit handles all of them, and the reasons are written into the code:
- A process that inherits the watchdog's lock holds it forever. Every later run exits silently and deploys just stop, with no error anywhere. It happened twice.
$!is the wrapper shell, not your server. Kill the wrong one and the old server keeps its port, so the next deploy can't start.- Two processes can't share a port. Any handoff of the public port is a gap, so the front door is never replaced while it serves. nginx changes by reload instead.
- "The port is open" isn't "ready". The first version would have switched traffic before a search index had loaded.
- Containers can't do the kernel-level tricks. There's no
NET_ADMIN,/proc/sysis read-only and the public port mapping can't be re-pointed. That's why this is nginx-based.
Status
Proven on Component Ocean. The next step is making it the standard way our service containers deploy. If you adopt it on your service, run the probe and add your numbers here.