SQLx Offline Mode
SQLx Offline Mode
Section titled “SQLx Offline Mode”Product: v0.19.0 · Related: Migration checksum gate
Overview
Section titled “Overview”EdgeQuake uses SQLx’s compile-time query verification, which by default requires a live database connection during compilation. This document explains how we’ve configured offline mode to allow builds without a running PostgreSQL instance.
Problem
Section titled “Problem”When building the backend with cargo build, SQLx’s query! and query_scalar! macros attempt to connect to PostgreSQL at compile time to verify SQL queries. If the database isn’t running, you’ll see errors like:
error: error communicating with database: Connection refused (os error 61) --> crates/edgequake-storage/src/adapters/postgres/pdf_storage_impl.rs:50:9Solution
Section titled “Solution”We use SQLx offline mode, which pre-generates query metadata when the database IS available, then uses this cached metadata for future builds.
Configuration
Section titled “Configuration”-
edgequake/.cargo/config.toml— Sets SQLx offline mode by default:[env]SQLX_OFFLINE = "true" -
edgequake/.sqlx/— Contains pre-generated query metadata (committed to git)
Workflow
Section titled “Workflow”Initial Setup (One Time)
Section titled “Initial Setup (One Time)”Generate SQLx metadata when you have database access:
# Start PostgreSQL (from repo root)make db-start
# Generate SQLx metadata (from repo root)make backend-sqlx-prepare
# Commit the metadata directorygit add edgequake/.sqlx/git commit -m "chore: add SQLx offline metadata"Regular Development
Section titled “Regular Development”With offline mode configured, you can build without a database:
# Build works WITHOUT database running (from repo root)make backend-build
# Or use cargo directlycd edgequake && SQLX_OFFLINE=true cargo build --releaseWhen to Regenerate Metadata
Section titled “When to Regenerate Metadata”Regenerate SQLx metadata whenever you:
- Add new SQL queries using
sqlx::query!,sqlx::query_scalar!, orsqlx::query_as! - Modify existing SQL queries
- Change database schema (migrations)
# Regenerate metadata (from repo root)make backend-sqlx-prepareAvailable Make Targets
Section titled “Available Make Targets”All targets live in the repo-root Makefile:
| Command | Description |
|---|---|
make backend-build |
Build backend in offline mode (DEFAULT) |
make backend-build-online |
Build with live database verification |
make backend-sqlx-prepare |
Generate SQLx metadata for offline builds |
backend-sqlx-prepare runs cargo sqlx prepare --workspace inside edgequake/ with DATABASE_URL pointed at the local Postgres container.
How It Works
Section titled “How It Works”-
Offline Mode Enabled:
SQLX_OFFLINE=truetells SQLx macros to read fromedgequake/.sqlx/instead of querying the database -
Metadata Files: Each
sqlx::query!invocation gets a JSON file inedgequake/.sqlx/containing:- Query text
- Parameter types
- Result column types
- Nullability information
-
Compile-Time Verification: SQLx still validates queries at compile time, but uses cached metadata instead of live database connection
Migration checksum gate (adjacency)
Section titled “Migration checksum gate (adjacency)”SQLx offline metadata and migration immutability are separate but related gates:
| Gate | Path / command | What it catches |
|---|---|---|
| SQLx offline | edgequake/.sqlx/ + make backend-sqlx-prepare |
Compile-time query/type drift without a live DB |
| Migration checksum | edgequake/migrations/checksums.lock + ./scripts/check_migration_checksums.sh |
Byte changes to already-deployed migration SQL (startup would fail with “migration N was previously applied but has been modified”) |
When you add or edit migration SQL, you must:
- Apply migrations locally (
make db-startthen restart backend, or run migrations manually) - Regenerate SQLx metadata if queries changed:
make backend-sqlx-prepare - Update the checksum lockfile:
./scripts/update_migration_checksums.sh - Commit
edgequake/.sqlx/,edgequake/migrations/checksums.lock, and the migration file together
CI runs check_migration_checksums.sh in the migration-checksum-guard job. Install local hooks with ./scripts/install_migration_hooks.sh to catch checksum drift before push.
Regression coverage: scripts/test_migration_e2e.sh (lease-view + checksum paths).
Benefits
Section titled “Benefits”✅ Faster CI/CD: No need to spin up PostgreSQL in build pipelines
✅ Offline Development: Build without database access
✅ Consistent Builds: Same query verification across all environments
✅ Reduced Dependencies: Build stage doesn’t need database credentials
Troubleshooting
Section titled “Troubleshooting”Error: “cached query must be loaded with SQLX_OFFLINE=true”
Section titled “Error: “cached query must be loaded with SQLX_OFFLINE=true””Cause: Query was added/modified but metadata not regenerated
Fix:
make backend-sqlx-prepareError: “query not found in .sqlx/”
Section titled “Error: “query not found in .sqlx/””Cause: Using a query that hasn’t been prepared yet
Fix:
# Ensure database is runningmake db-start
# Regenerate metadatamake backend-sqlx-prepareBuild fails with “Connection refused” even with SQLX_OFFLINE=true
Section titled “Build fails with “Connection refused” even with SQLX_OFFLINE=true”Cause: Environment variable not set or edgequake/.sqlx/ directory missing
Fix:
# Check configcat edgequake/.cargo/config.toml | grep SQLX_OFFLINE
# Verify .sqlx/ existsls -la edgequake/.sqlx/
# Regenerate if missingmake backend-sqlx-prepareCI fails migration-checksum-guard after editing SQL
Section titled “CI fails migration-checksum-guard after editing SQL”Cause: Migration file bytes changed but checksums.lock not updated
Fix:
./scripts/update_migration_checksums.shgit add edgequake/migrations/checksums.lockReferences
Section titled “References”- SQLx Offline Mode Documentation
- EdgeQuake Makefile —
backend-sqlx-preparetarget - edgequake/.cargo/config.toml — SQLx configuration
- scripts/check_migration_checksums.sh — CI immutability gate