Homework — prove the schema can't drift
Prove the "no drift" claim yourself. This is the homework that makes the lesson stick.
-
Add a column with a new migration. Migrations are append-only — you don't edit an applied one, you add the next. Create
db/migrations/00002_user_name.sql:-- +goose Up ALTER TABLE users ADD COLUMN full_name TEXT NOT NULL DEFAULT ''; -- +goose Down ALTER TABLE users DROP COLUMN full_name; -
Regenerate — and touch no Go.
sqlc generateOpen
internal/db/models.go. TheUserstruct grew aFullName stringfield on its own — because sqlc re-read the schema (now two migrations) and the struct is a function of it. You edited zero Go by hand. -
Now feel the drift protection bite. Write a query that selects the new column —
-- name: GetUserName :one\nSELECT full_name FROM users WHERE id = $1;— then misspell it asfull_name. Runsqlc generate:error: column "full_name" does not existThe typo is caught at generate time, against the real schema — not at runtime, in production, on a user's request. That's the whole promise, demonstrated: the generated code cannot describe a table that doesn't exist. Fix the typo, regenerate, and it's clean.
-
Restart and re-migrate.
go run ./cmd/signflow— the log showsOK 00002_user_name.sqlapplying. Your live database now has the column; a fresh deploy would apply both migrations from scratch.
Where this is going. You have a users table with a password_hash column that nothing fills yet. Lesson 4 starts the auth phase: registration with bcrypt password hashing, and server-side sessions — a session row in Postgres, an opaque ID in an HttpOnly cookie. It's the first time SignFlow knows who you are — and the beginning of the answer to a question the Pica mobile app answered differently: sessions, not JWT. Lesson 14 is the whole argument for why.