Database and storage
Set up local SQLite storage, retention, backups, and temporary storage for the CLI.
The CLI uses SQLite for traces. SQLite is bundled
into the binary: you do not need to install a database server, create tables, or
run migrations. The CLI creates its database and schema automatically when you
run route, replay, debug, or serve.
Omit database to use data/traces.db beside the configuration file. Storage
and retention settings are optional.
Choose a storage option
Section titled “Choose a storage option”| Option | Configuration | Behavior |
|---|---|---|
| Persistent SQLite file | "database": "../data/traces.db" |
Keeps traces between commands and restarts |
| Temporary in-memory SQLite | "database": ":memory:" |
Loses all data when the command exits |
Use a persistent file for debugging and replay. PostgreSQL, MySQL, object-storage backends are not supported by the CLI.
Set up a persistent database
Section titled “Set up a persistent database”In your CLI configuration, set database to a file path. The repository’s
examples/olyx.json already uses ../data/traces.db:
Update these storage fields in your complete configuration, keeping its existing model aliases:
{ "database": "../data/traces.db", "policy": { "retention_days": 30 }}You can also use an absolute path, such as /var/lib/olyx/traces.db. On Windows,
escape backslashes in JSON, for example "C:\\Users\\you\\olyx\\traces.db".
Use a concrete path: shell shortcuts such as ~ and $HOME are not expanded
inside the JSON file.
From the CLI repository directory:
export OPENAI_API_KEY=your-provider-keyolyx check examples/olyx.jsonolyx route --config examples/olyx.json --input examples/request.jsonolyx debug --config examples/olyx.jsoncheck validates configuration but does not create the database or test directory
permissions. The first local runtime command creates missing parent directories
and opens the database. Its directory must be writable by the user running the CLI.
What is stored
Section titled “What is stored”The database stores trace metadata, recorded model requests and responses, attempted models, failures, and latency.
SQLite uses write-ahead logging with full synchronous commits. You may see traces.db-wal and traces.db-shm
beside the database. Keep these files on the same local filesystem as the database;
do not remove them while commands are running. Prefer local disk over a network
share or a directory managed by a file-sync application.
On Unix, newly created storage directories are owner-only (0700); database and
journal files are owner-only (0600). Existing directories retain their existing
permissions. On Windows, use a directory restricted to your user account.
File permissions protect access; the CLI does not encrypt the database.
Recover after an interrupted process
Section titled “Recover after an interrupted process”If Olyx stops before a request finishes, the next command that opens the same
database checks whether the process that owned the trace is still running.
Abandoned traces become failed with the diagnostic code request_interrupted.
Requests still owned by an active CLI process remain pending.
olyx debug --config olyx.jsonolyx debug TRACE_ID --config olyx.jsonReplace TRACE_ID with the interrupted trace’s ID. Saved provider attempts remain
available. Recovery does not resend requests: a provider may already have processed
the original request and incurred usage. Inspect the trace before retrying.
Pending traces written by older versions without ownership records are left
unchanged because Olyx cannot safely determine whether their requests are active.
Corrupt stored JSON raises a storage error rather than being returned as null.
Configure retention
Section titled “Configure retention”Set policy.retention_days to a positive integer. The default is 30 days.
{ "policy": { "retention_days": 90 }}Merge this setting into your complete configuration. Expired traces and their steps are deleted when a local runtime command opens the database. There is no background cleanup process. Expired traces cannot be replayed. Shortening retention takes effect the next time you run a local runtime command.
Back up and restore
Section titled “Back up and restore”Use SQLite’s backup facility for a consistent copy that includes committed data
in the WAL. If you have the optional sqlite3 command installed, run this from
the repository directory:
mkdir -p backupssqlite3 data/traces.db ".backup 'backups/traces.db'"The sqlite3 command is a backup utility; it is not required to run Olyx. Another
option, if Python 3 is installed, is its standard-library SQLite backup API:
from pathlib import Pathimport sqlite3
Path("backups").mkdir(exist_ok=True)with sqlite3.connect("file:data/traces.db?mode=ro", uri=True) as source: with sqlite3.connect("backups/traces.db") as destination: source.backup(destination)Backups contain recorded payloads, so store them with appropriate access
permissions. To use a backup, stop any commands using it, make a working copy,
and set database in a configuration file to that copy’s path. Opening the copy
also applies the configuration’s retention policy.
Temporary storage
Section titled “Temporary storage”{ "database": ":memory:"}Replace only database in an otherwise complete configuration. This is useful for
a throwaway routing run. Each CLI invocation starts a new database, so a later
debug or replay command cannot find traces from an earlier invocation. Use a persistent file to keep traces across commands.
Troubleshooting
Section titled “Troubleshooting”| Symptom | What to check |
|---|---|
| Cannot open database | Check the resolved path and parent-directory permissions |
| Trace not found | Use the same configuration/database as the original route; check retention and avoid :memory: |
request_interrupted |
The owning process ended; inspect saved attempts before explicitly retrying |
| Database is locked | Let the other writer finish; the CLI waits up to five seconds for SQLite locks |
Continue with the quickstart or Olyx CLI overview.