Skip to content

← all backend comparisons

baseline

Typed SQL: sqlc vs sqlx::query!

Both backends serve the same /products endpoints. The contrast is in how the SQL is written and checked — sqlc generates Go from a .sql file offline; sqlx checks inline SQL against a live database at compile time.

Go (chi · sqlc · pgx)
You write SQL …
go/internal/store/queries.sql
// shop-two-backends not found at build time
… and call the generated method
go/internal/httpserver/products.go
// shop-two-backends not found at build time
Rust (axum · sqlx · tokio)
SQL is inline; the macro checks it at compile time
rust/src/routes/products.rs
// shop-two-backends not found at build time

What to take away

sqlc reads queries.sql at code-gen time (no DB needed) and emits Go methods on a Queries struct. Run sqlc generate after editing SQL. The generated code is checked into the repo.

sqlx::query_as! macro-expands at compile time, connecting to a live Postgres to verify column names, types, and nullability. Get a typo wrong and cargo check refuses the build. For Docker builds we use SQLX_OFFLINE=true and a committed .sqlx/ snapshot so production builds need no DB access.

Both eliminate the typo-in-runtime scenario. sqlc has a more Go-idiomatic generated-code feel; sqlx feels closer to the SQL but requires snapshotting metadata for hermetic builds.