Skip to content

Persistence

Kaio stores its state in SQLite, managed with SQLx. The layer is designed for a containerised single-host deployment: no external service, one file, atomic state.

Centralised management. All database logic (initialization, pooling, migrations) lives in backend/crates/core/src/db.rs. The server and the CLI reuse the same layer rather than each opening their own connection with their own assumptions.

WAL mode. Write-Ahead Logging is enabled by default, allowing multiple concurrent readers alongside a single writer. This is what keeps metrics collection from colliding with dashboard reads and producing database is locked errors.

Automated migrations. The core crate embeds the migrations with sqlx::migrate! and runs them on startup, so a fresh deployment and an upgraded one converge on the same schema with no manual step.

Atomic state. Stacks, container history and events are written atomically, so an unexpected shutdown leaves a consistent database: a half-written stack version does not exist.

WAL is set when the pool opens, so the database always comes with its two companion files:

Terminal window
$ ls data/
kaio.db kaio.db-shm kaio.db-wal stacks/
$ sqlite3 data/kaio.db "pragma journal_mode;"
wal

Those three files are one database. Copying only the .db gives an incomplete snapshot, which is why Backup and restore uses SQLite’s own backup command.

Store Holds
SQLite Metadata, metrics, events, version snapshots, scan results
Filesystem (./data/stacks/<name>/) The live compose.yml and .env

Compose needs real files on disk to run, so the current state of a stack is a file; its history is a database row. Both live under data/, which is the only directory you need to back up or mount.

The server is the single background writer. Running two server instances against the same database file will produce lock contention. See Troubleshooting.

See the database schema for the tables and indexes.

Kaio, built by Régis Gaidot