# Versioned migrations Each schema change is a separate `.sql` file, applied in alphabetical order. Applied files are tracked in the `_migrations` table. ## Applying migrations ```sh npm run migrate # apply pending migrations (safe to re-run) npm run migrate:bootstrap # mark 000_baseline.sql as applied on existing DB (run ONCE per env) npm run migrate:legacy # run legacy migrate.js (kept for reference, do not use) ``` ## Naming convention ``` NNN_short_description.sql ``` Examples: `001_add_user_avatar.sql`, `002_drop_unused_columns.sql` To find the next number: ```sh ls backend/src/db/migrations/*.sql | sort -r | head -1 ``` ## Rules 1. **Never edit** a migration file after it has been committed and deployed. 2. To revert: write a new migration that undoes the change. 3. Each file must be valid SQLite SQL (not PostgreSQL — no SERIAL, no EXTENSION). 4. Use `IF NOT EXISTS` / `IF EXISTS` where possible for safety. 5. Test on a copy of the prod DB before deploying. ## Deploy order (first time on a new environment) ```sh npm run migrate:legacy # initialize full schema (existing init script) npm run seed:permissions # seed default permissions and achievements npm run migrate:bootstrap # mark 000_baseline.sql as applied npm run migrate # apply any newer migrations (should say "nothing to apply") npm start ``` ## Adding a new migration ```sh # 1. Create the file echo "ALTER TABLE users ADD COLUMN avatar_url TEXT;" > backend/src/db/migrations/001_add_avatar_url.sql # 2. Apply and verify npm run migrate # 3. Commit git add backend/src/db/migrations/001_add_avatar_url.sql git commit -m "db: add avatar_url column to users" ``` ## Files | File | Description | |------|-------------| | `000_baseline.sql` | Snapshot of full schema as of 2026-05-06. Never runs on existing DBs. |