Stores
Workflow instances need to live somewhere. The store holds every running workflow’s state, context, and version number. You pick the store that matches your deployment.
Store kinds
Section titled “Store kinds”| Kind | Durability | Best for |
|---|---|---|
memory | None — lost on restart | Development, testing |
file | Disk (one JSON file per workflow) | Simple single-server production; easy to back up |
sqlite | Disk (bundled, WAL mode) | Single-host production; the only backend with durable Evidence + acknowledgment stores |
memory
Section titled “memory”The default. Instances live in process memory and disappear when the gateway stops.
store: kind: memoryFast and zero-config. Good for development, testing, and short-lived processes where you don’t need workflows to survive a restart.
Persists each workflow instance as its own JSON file under a configured directory. Uses atomic-rename writes and optimistic locking on version.
store: kind: file path: /var/lib/flowgate/workflowsThe gateway creates the directory automatically. Each workflow gets one file (<workflowId>.json). Atomic-rename writes mean a snapshot taken mid-write is always either the old or new version — never a partial file. Good for single-server production where you want a simple, backup-friendly layout.
sqlite
Section titled “sqlite”Persists instances to a SQLite database file. Uses WAL mode for good concurrent-read performance.
store: kind: sqlite path: ./data/workflows.dbThe gateway creates the database file and parent directories automatically. The schema is one table:
CREATE TABLE workflows ( id TEXT PRIMARY KEY, version INTEGER NOT NULL, instance TEXT NOT NULL -- JSON-serialized workflow instance);SQLite is a solid choice for production deployments. No extra infrastructure, no network hops. The database file is just a file you can back up, inspect, and move. It is bundled (via rusqlite, WAL mode), and it is the only backend that keeps Evidence and acknowledgment stores durable — memory and file keep those in process memory. Multiple processes on a single host can share one SQLite file; there is no networked store, so state is not shared across hosts.
Optimistic locking
Section titled “Optimistic locking”All stores enforce optimistic locking. When you call flowgate.command({workflowId, transition, expectedVersion}) (submit), you pass an expectedVersion. The store checks this against the current version before saving:
- Read the instance and its version.
- If
expectedVersiondoesn’t match, reject withSTALE_WORKFLOW_VERSION. - If it matches, apply the transition and increment the version.
For SQLite, this is implemented as:
UPDATE workflows SET version = ?, instance = ?WHERE id = ? AND version = ?If zero rows are affected, the version was stale — someone else got there first. The gateway returns an error with the current state so the caller can retry.
This matters most when multiple actors (model + human, or multiple models) are working on the same workflow. The optimistic lock prevents lost updates without heavyweight locking.
Choosing a store
Section titled “Choosing a store”Development? Use memory. No config needed, fast iteration.
Single server in production? Use sqlite. Workflows survive restarts, and it’s the only backend with durable Evidence and acknowledgment stores. Zero ops overhead — it’s just a file. Multiple processes on the same host can share one SQLite file. Or use file if you prefer individual per-workflow JSON files (easier to inspect and back up individually) and don’t need durable governance state.
Cross-host high availability? Not supported — there is no networked store backend. State is shared only between processes on a single host (via a shared SQLite file). If you need another backend, you can implement the WorkflowStore trait yourself; nothing beyond memory, file, and sqlite ships built in.
You can switch stores without changing anything else in your config. The gateway’s behavior is identical regardless of store; only durability and deployment topology change.