Skip to main content
Reality Oracle
OverviewCitizensReality FeedVerified ActorsIntel SubscribersMarket PredictionInvestment FundsHow It WorksGates
Products
Backtest ForensicsLiving MapDrift AlertsPath QueriesCustom AxesRisk Maps
Solutions
Compliance OfficersRisk Managers / CROPortfolio ManagersCTOs & Engineering
Enterprise
Enterprise OverviewReality Oracle · SuperappThe AppsArchitectureAudit ManifestTrust CenterPricing
Developers
DocumentationAPI ReferenceSDKsArchitectureAudit Manifest
Resources
BlogUse CasesCustomer StoriesPressChangelog
Company
AboutFoundersCareersContact
Trust
Trust Center
More
PricingJoin Waitlist
··11 min read

Compile-time-checked SQL, or: why .sqlx is committed

The offline cache lets CI build without a live DB — and why editing SQL means refreshing it.

Compile-time-checked SQL, or: why .sqlx is committed

sqlx checks SQL at compile time. That is not a feature; it is a contract — the queries in the binary are the queries that will run, and the .sqlx/ offline cache is what makes that contract hold in CI without a live database.

sqlx checks SQL at compile time. That is not a feature; it is a contract — the queries in the binary are the queries that will run, and the .sqlx/ offline cache is what makes that contract hold in CI without a live database.

Compile-time, not runtime

sqlx is a Rust SQL toolkit that can check queries at build time against a database schema. The check is literal: the SQL string in your code is prepared against the actual Postgres schema, and if the query references a column that does not exist, the build fails. The query is verified before the binary exists, not when it runs. That is the property: a malformed query is a compile error, not a 2 a.m. production error. The cost is that the build needs to see the schema — either a live database, or the offline cache.

The .sqlx/ cache: each query string mapped to its prepared result. The build reads the cache; CI builds without a live DB; editing SQL means refreshing it.
The .sqlx/ cache: each query string mapped to its prepared result. The build reads the cache; CI builds without a live DB; editing SQL means refreshing it.

The offline cache is committed

DEINO commits the .sqlx/ directory to the repo — currently dozens of prepared-query entries. With SQLX_OFFLINE=true, sqlx reads the cache instead of connecting to a live database, so cargo build, cargo check, and clippy all run without a Postgres. That is what makes CI offline-buildable: the schema knowledge is in the repo, not behind a running service. The trade-off is discipline: every time you edit a SQL query, you run just sqlx-prepare (which needs a DATABASE_URL) and commit the refreshed .sqlx/. Skip that, and the offline build breaks — the cache no longer matches the code.

A malformed query is a compile error, not a 2 a.m. production error. The .sqlx/ cache is what makes that true in CI without a live database.

Why the cache is committed, not generated in CI

The alternative is to run a live Postgres in CI, prepare the queries against it, and throw it away. That works and it is heavier. The committed cache is lighter — CI does not need a database to build — and it is more honest about what the build depends on: the schema as recorded in the cache, not the schema as it happens to be in a CI database spun up minutes ago. The cache is a committed artifact that reflects a specific schema state, and refreshing it is an explicit step, not an implicit one. That makes the schema change visible in the diff, alongside the code change that motivated it.

  • Compile-time checks: a query against a missing column fails the build, not the runtime.
  • SQLX_OFFLINE=true + committed .sqlx/ means CI builds without a live DB.
  • Editing SQL means running just sqlx-prepare and committing the refreshed cache — skip it and the offline build breaks.

The discipline it enforces

The committed cache is a discipline mechanism. It means you cannot change a query and forget to update the schema, because the cache will not match and the offline build will fail. It means you cannot change the schema and forget to update the queries, for the same reason. The cache is a lockstep record of the queries and the schema, and breaking that lockstep is a build failure, not a silent drift. That is the value of compile-time SQL: not speed, correctness — the kind that surfaces at build time, not at runtime.

The cache is a committed lockstep record of the queries and the schema. Breaking that lockstep is a build failure, not a silent drift — and that is the value of compile-time SQL.

— sqlx offline-cache note

What it is not

Compile-time SQL is not a claim that queries are correct. It is a claim that queries are well-formed against the schema — they reference real columns and real tables. A query that is well-formed but returns the wrong rows is still a bug, and sqlx does not catch that. The catch is that the class of bugs sqlx does catch — the malformed-query class — is moved from runtime to build time, which is a pure win. We are pre-revenue and building the POC; the .sqlx/ cache is committed, and the offline build is what CI runs.

§Keep reading