ADR-029 — Compose sidecar services for recipe save and video export
Status · Accepted Date · May 2026 TA anchor · components/service-layer · components/web-frontend · stack Related · ADR-011 (Docker Compose deployment) · ADR-012 (Caddy)
Context
ADR-011 records the original four-service Compose stack: postgres, prefect-server, pipeline, and gallery. The Recipe Editor and Video Editor need small, state-changing HTTP endpoints: persisting edited recipe YAML to disk, and invoking the pipeline’s export path to assemble MP4s. Those concerns do not belong inside the static gallery container’s core responsibility (serving the React build and proxied assets).
Decision
Add two dedicated Node.js 20 sidecar services in compose/docker-compose.yml:
recipe-server— listens on port 3001;POST /api/recipes/{slug}writes YAML underrecipes/. Thegalleryservice’s Caddy reverse-proxies/api/recipesto this container.export-server— listens on port 3002; triggersoceancanvas export-video(or equivalent) for timelapse export, with access torenders/and read-onlyaudio/.
Together with the four services above, the production Compose stack is six services. ADR-011 remains the record of “Compose is the deployment model”; this ADR records the service count and sidecar pattern that evolved after that decision.
Rationale
- Keeps Caddy’s role clear: static files plus narrow reverse-proxy to known upstreams.
- Sidecars stay tiny (single-purpose scripts under
gallery/server/), rebuild independently of the pipeline image, and mount only the volumes they need. - Preserves ADR-005 (no application database): Postgres remains Prefect-only; recipe state stays file-based YAML on disk.
Alternatives considered
- Embed save/export inside the pipeline container — couples authoring UX to the batch worker image and complicates permissions on
recipes/andrenders/. - Browser-only writes to disk — impossible in a static deployment without an unsafe generic upload server.
- Third-party object store for recipes — violates file-based v1 storage and self-hostable defaults.
Consequences
Positive:
- Recipe authoring and export work through the same
docker compose upstory as the rest of the stack. - Clear separation between read-mostly gallery assets and write endpoints.
Negative:
- Operators must expose / health-check two extra ports (3001, 3002) on the host when debugging.
- Documentation must always list six services, not four.
Implementation notes
compose/docker-compose.yml—recipe-serverandexport-serverservice definitions;gallerydepends_onincludesrecipe-server.gallery/Caddyfile—/api/recipesproxy to recipe-server.gallery/server/save-recipe.mjs,gallery/server/export-video.mjs.