State Management

Oxid stores infrastructure state in a real database - SQLite for local development, PostgreSQL for teams. State is queryable with SQL, versioned with history, and supports concurrent access.

Overview

Unlike Terraform, which stores state in a single JSON file, Oxid uses a relational database. This gives you:

  • SQL queries - Query your infrastructure with standard SQL
  • Built-in history - Every change is recorded automatically
  • Concurrent access - Multiple operations can read state simultaneously
  • No state locking issues - Database transactions handle concurrency
  • Structured storage - Resources, outputs, dependencies, and runs are stored in separate tables

SQLite (Default)

By default, Oxid creates a SQLite database at .oxid/oxid.db. This is perfect for individual use and local development.

$ oxid init
# Creates .oxid/oxid.db

$ oxid query "SELECT COUNT(*) FROM resources"
+----------+
| COUNT(*) |
+----------+
| 24       |
+----------+
NoteSQLite requires no external dependencies or configuration. It is created automatically during oxid init.

PostgreSQL (Teams)

For team workflows, set the OXID_DATABASE_URL environment variable to use PostgreSQL:

export OXID_DATABASE_URL="postgresql://user:pass@host:5432/oxid_state"
oxid init

PostgreSQL provides:

  • Shared state across team members
  • Encrypted sensitive outputs via pgcrypto
  • Full PostgreSQL query capabilities
  • Connection pooling for concurrent access

See PostgreSQL Backend for detailed setup.

Database Tables

resources

All managed resources with their current attributes, provider, and status.

oxid query "SELECT address, type, status FROM resources LIMIT 5"

outputs

Output values defined in your configuration, evaluated during apply.

oxid query "SELECT name, value, sensitive FROM outputs"

runs

History of plan and apply operations with timestamps and resource counts.

oxid query "SELECT id, action, created, resources_changed FROM runs ORDER BY created DESC LIMIT 5"

dependencies

Resource dependency edges used to build the execution graph.

oxid query "SELECT source, target FROM dependencies WHERE source = 'aws_vpc.main'"

resource_history

Timestamped record of every resource change, including before/after diffs.

oxid query "SELECT address, action, created_at FROM resource_history ORDER BY created_at DESC LIMIT 10"

State Operations

Oxid provides several commands for working with state:

Backup and Recovery

SQLite backup

# Simple file copy
cp .oxid/oxid.db .oxid/oxid.db.backup

# Or use SQLite's backup command
sqlite3 .oxid/oxid.db ".backup backup.db"

PostgreSQL backup

pg_dump -t 'oxid_*' $OXID_DATABASE_URL > oxid_state_backup.sql