Skip to main content
Version: 1.0.0

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​

DataDefault locationSetting
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 journalhost-selected .sqlite path--effect-journal
Approvals, checkpoints and interactionsseparate databases in .touba/project server
Compensationshost-selected .sqlite pathcreateSqliteCompensationStore

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.