Schema migrations: change a database safely
A migration is a versioned change to your database schema. This example adds a column to a Notes application without deleting existing records.
1. Create the original table
CREATE TABLE notes (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL
);
INSERT INTO notes (id, title) VALUES (1, 'Read a book');
2. Write your first migration
The new application must track when a note was created:
ALTER TABLE notes ADD COLUMN created_at TEXT;
UPDATE notes SET created_at = '2026-11-01' WHERE created_at IS NULL;
The first statement changes the schema. The second statement backfills existing rows.
3. Verify the result
SELECT id, title, created_at FROM notes;
Expected columns: id, title, created_at. Your existing note remains.
4. Record applied migrations
CREATE TABLE IF NOT EXISTS schema_migrations (
version TEXT PRIMARY KEY,
applied_at TEXT NOT NULL
);
INSERT INTO schema_migrations (version, applied_at)
VALUES ('001_add_created_at', '2026-11-01');
The migration runner uses this table to skip changes already applied.
5. Production workflow
Back up important data before changing schemas. Review the generated SQL, apply changes in a transaction when supported by your database, and keep backward-compatible releases when multiple app versions may be running.
See SQLite and PostgreSQL for the database engines.