Stage 3 · Build
Databases & Persistence
sqlc and GORM
Compare generated type-safe queries from sqlc with GORM models, associations, and query builders.
Why Code Generation
Writing raw SQL strings in Go is error-prone. Typos in column names, type mismatches, and forgotten parameters cause runtime errors. Code generation tools produce type-safe Go code from SQL or schema definitions, catching errors at compile time.
sqlc Approach
sqlc generates Go code from SQL queries. You write SQL in .sql files, sqlc generates type-safe Go functions. Your SQL is the source of truth. You control the queries, sqlc generates the plumbing.
version: "2"
sql:
- engine: "postgresql"
queries: "sql/queries/"
schema: "sql/schema/"
gen:
go:
package: "db"
out: "internal/db"
sql_package: "pgx/v5"
emit_json_tags: true
emit_db_tags: truesqlc reads your SQL schema and query files, then generates Go code with proper types, error handling, and database driver integration.
GORM Approach
GORM is an ORM that maps Go structs to database tables. It provides a query builder, associations, hooks, and migrations. You write Go code, GORM generates SQL. The opposite direction from sqlc.
sqlc Example
-- name: GetUser :one
SELECT id, email, name, created_at
FROM users
WHERE id = $1
LIMIT 1;
-- name: ListUsers :many
SELECT id, email, name, created_at
FROM users
ORDER BY created_at DESC
LIMIT $1 OFFSET $2;
-- name: CreateUser :one
INSERT INTO users (email, name, password_hash)
VALUES ($1, $2, $3)
RETURNING id, email, name, created_at;
-- name: UpdateUser :exec
UPDATE users
SET name = $2, updated_at = now()
WHERE id = $1;
-- name: DeleteUser :exec
DELETE FROM users WHERE id = $1;sqlc uses query comments to determine the return type: :one for single rows, :many for multiple rows, :exec for commands that return nothing.
GORM Example
Tradeoffs
| Criteria | sqlc | GORM |
|---|---|---|
| SQL control | Full — you write every query | Generated — GORM decides |
| Type safety | Compile-time | Runtime errors possible |
| Performance | Optimal — hand-tuned SQL | Overhead from abstraction |
| Learning curve | Must know SQL | Lower — Go-native API |
| Migration support | Separate tool | Built-in AutoMigrate |
| Associations | Manual JOINs | Automatic Preload |
sqlc is better for teams that know SQL and want full control. GORM is better for teams that prefer Go-native APIs and want rapid prototyping. Both are production-ready. Many projects use sqlc for complex queries and GORM for simple CRUD.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.