Skip to content

← all backend comparisons

correctness

sqlx::query! — the demo that converts skeptics

Delete a column from your migration and rebuild. sqlx::query! refuses to compile and tells you exactly which call site references the missing column. No tests, no DB roundtrip in production code, no surprise at 3am.

Go (chi · sqlc · pgx)
sqlc reads this offline — typo only caught when sqlc generate runs
go/internal/store/queries.sql
// shop-two-backends not found at build time
Rust (axum · sqlx · tokio)
sqlx::query_as! talks to a live Postgres at compile time
rust/src/routes/products.rs
// shop-two-backends not found at build time

What to take away

Pretend you delete the category column from migrations/0001_init.up.sql and run the migration.

Rust: cargo check dies inside routes/products.rs with "column 'category' does not exist" pointing at the SELECT … category … line of the macro. You can't even build a binary that references the missing column.

Go: sqlc generate only re-validates when explicitly run. Forget to run it and the generated code keeps compiling against the old schema; the failure surfaces at the first runtime call, not at build time.

For hermetic Docker builds, sqlx switches to SQLX_OFFLINE=true and reads from a committed .sqlx/ snapshot. cargo sqlx prepare refreshes the snapshot. The compile-time check is preserved against the snapshotted schema even when no live DB is reachable.