Storage and retention
Touba stores growing execution state in local SQLite databases. SQLite ships with the runtime and requires no database server. The host application chooses storage paths, quotas and retention periods.
Storage settings
| Data | Default location | Setting |
|---|---|---|
| Traces | .touba/traces.sqlite | --trace-store; webhook service: --trace-max-bytes |
| Admitted events and daily counts | .touba/triggers.sqlite | --state, --state-max-bytes |
| Webhook queue | .touba/trigger-queue.sqlite | --queue, --queue-max-bytes, --queue-max-entries |
| Effect journal | host-selected .sqlite path | --effect-journal |
| Approvals, checkpoints and interactions | separate databases in .touba/ | project server |
| Compensations | host-selected .sqlite path | createSqliteCompensationStore |
Each database has a default 512 MiB quota. The queue accepts 10,000 entries. For traces, this quota counts JSON headers and events; SQLite indexes and its transaction journal need additional space. Reserve disk headroom and monitor the actual file sizes as well. Storage operations check identities and revisions. A storage failure or full quota stops the affected work while retaining durable state. External effects keep their own idempotency and recovery contracts.
Read pages
touba trigger state .touba/triggers.sqlite --limit 100
touba trigger queue .touba/trigger-queue.sqlite --limit 100
touba state list effects .touba/project.effect-journal.sqlite --limit 100
touba state list compensations .touba/compensations.sqlite --limit 100
Pass the returned next cursor to --after to continue. Pages contain up to
1,000 items. Traces also support paged reads
through the CLI and both SDKs.
Archive completed work
Trigger archival copies completed details into a new database, verifies their
digest and removes them from the current database only with --apply.
Consumed identities and daily counts remain to prevent replay.
touba trigger archive-state .touba/triggers.sqlite --before 2026-10-01T00:00:00Z
touba trigger archive-state .touba/triggers.sqlite --before 2026-10-01T00:00:00Z --out archives/triggers.sqlite --apply
touba trigger archive-queue .touba/trigger-queue.sqlite --before 2026-10-01T00:00:00Z --out archives/queue.sqlite --apply
The queue archives successful entries. Active, failed and uncertain work stays
available for recovery. Read archives with the same state and queue commands.
The project server also provides touba serve --archive-state and
--restore-state <id> for offline state. Review the preview before adding --apply.
Migrate older state
Stop writers first. Validate the migration, then create the new database:
touba state migrate effects old.effect-journal.json --out .touba/effects.sqlite
touba state migrate effects old.effect-journal.json --out .touba/effects.sqlite --apply
touba trigger migrate-state old.trigger-state.json --out .touba/triggers.sqlite --apply
touba trigger migrate-queue old.queue.json --out .touba/trigger-queue.sqlite --apply
state migrate accepts effects, compensations, checkpoints,
human-requests, human-decisions, interaction-sessions and interaction-assets.
Records must satisfy current contracts. Each source is retained with an exact
.source-backup.json copy. Existing destinations are refused. Migration does
not execute work or create approval evidence.
For project-server state, migrate related collections together and run
touba serve --check-state before restarting. Retain asset files alongside their
metadata. The program, manifest and host modules must match the retained checkpoints.
Export to PostgreSQL
A separate process progressively sends traces to PostgreSQL. Program execution keeps writing to SQLite; pending evidence remains on disk until the destination acknowledges it.
touba trace export --store .touba/traces.sqlite --postgres-env TRACE_DATABASE_URL
touba trace export --store .touba/traces.sqlite --postgres-env TRACE_DATABASE_URL --watch
Set TRACE_DATABASE_URL in the export process environment using a dedicated
PostgreSQL account. The command prepares the touba_traces schema on first use.
Outside loopback, the CLI requires TLS with certificate and hostname validation.
Credentials stay out of command arguments and diagnostics.
Batches contain up to 100 events by default; --batch-size accepts 1 to 1,000.
A single pass processes up to 100 batches, adjustable with --max-batches.
--watch continues exporting, with increasing retry delays during outages.
Stop the process with Ctrl+C or SIGTERM.
The local cursor advances after the remote COMMIT. A lost reply allows the same batch to be resent; PostgreSQL checks identities and digests. Increasing lease epochs reject replaced workers. Local archival protects traces that still await acknowledgement from a configured destination.
Evidence remains readable locally after export. Removing local evidence is an explicit retention decision. This mechanism coordinates export workers; application execution workers retain their own coordination requirements.
Operations
Back up databases while writers are stopped. Protect their directories as application data; SQLite does not provide encryption at rest. Monitor disk space, queue depth and waiting operations, then choose retention periods that meet your audit needs.