Skip to main content
The orchestrator holds real work that is not in your CMS yet — drafts people have not published, undo history, the version log. This page is what an operator needs to know about where that lives and how to keep it.

One SQLite file

Session state — draft pages, history, the version log, chat history, site configs, issue-touched slugs — lives in a single SQLite file managed by better-sqlite3. Mutations are coalesced: a request’s synchronous writes are debounced for 30 ms and then snapshotted into SQLite inside one transaction, rather than each write hitting the disk on its own.

Files on disk

Under .data/ by default:
.data/ must be in .gitignore. The orchestrator writes it into the project root on the first request, and create-next-app’s .gitignore does not cover it — so the first git add . after the first run commits a database.

Configuration

Backups

A periodic VACUUM INTO writes a consistent snapshot without stopping the server — every 24 hours by default, keeping the last 14. That gives you point-in-time recovery inside the retention window and nothing outside it. If the draft state matters to you, copy those snapshots off the volume, the same way you would for any other database. Snapshot count and interval are the two dials. Restoring is a file copy: stop the orchestrator, put the snapshot in place of orchestrator.db (removing the -wal and -shm files alongside it), start it again.

What is capped

State does not grow without limit. The caps are per site, and hitting one discards the oldest entry rather than failing: The practical consequence for the people using the editor is on review and undo: history is deep, but it is not forever.

What is not persisted

Several things live only in memory and are gone on restart, by design:
  • pending approval plans awaiting an Apply/Discard decision
  • continuation chains
  • publish status
  • per-session image-source preferences
So a restart mid-review loses the held plan, not the draft. The person is asked again; nothing they had already applied is affected.

Shutdown

SIGTERM and SIGINT run three steps in order:
  1. app.close() — drain in-flight handlers
  2. persistStateNow — flush any debounced write
  3. resetStore() — checkpoint the WAL
Give the container time to do that. A hard kill during step 1 can lose up to the last 30 ms debounce window, and skipping step 3 leaves a WAL for the next boot to recover from — survivable, but not free.

Running with no durable state

Setting ORCHESTRATOR_DB_FILE=:memory: is legitimate for a public demo or an ephemeral preview environment, where losing drafts on restart is the point. Demo mode is the other half of that setup. Anywhere else, a serverless or otherwise ephemeral filesystem is a trap: the orchestrator will appear to work and silently lose every draft that was not published before the instance recycled.

Deploying

  • Docker — mount a persistent volume at the directory holding ORCHESTRATOR_DB_FILE
  • Vercel and Netlify — the site and editor deploy there; the orchestrator needs somewhere with a real disk
  • Security and access — what has to be set before any of this is reachable