Migrations
Tracera uses a simple file-based migration system. SQL files in themigrations/ directory are executed in order on server startup.
How It Works
- On startup, the server reads all
.sqlfiles frommigrations/ - Files are sorted by filename (numeric prefix)
- Each migration is applied in a transaction
- Already-applied migrations are tracked and skipped
Current Migrations
| File | Description |
|---|---|
001_auth.sql | Creates users and auth_providers tables with indexes and triggers |
002_auth_provider_user_provider_unique.sql | Adds unique constraint on (user_id, provider) and deduplicates legacy rows |
Naming Convention
Migrations follow a strict naming convention:- Sequence number — zero-padded three-digit number (e.g.,
001,002,003) - Description — snake_case description of the change
- Strict sequence continuity — no gaps allowed between sequence numbers
Validation
Themake migration-check target validates:
- Filename convention is followed
- Sequence numbers are continuous (no gaps)
- No merge conflict markers exist in migration files
Writing Migrations
Do’s
- Use
IF NOT EXISTS/IF EXISTSfor idempotent operations - Wrap destructive operations in transactions
- Test migrations against a real database with
make db-check - Include
DOWNlogic as comments for documentation (not auto-executed)
Don’ts
- Never modify an existing migration file after it’s been applied in production
- Never delete migration files
- Never leave gaps in sequence numbers
- Avoid long-running locks (e.g., adding indexes on large tables without
CONCURRENTLY)
Testing Migrations
db-check target spins up a temporary TimescaleDB container, applies all migrations, and validates the resulting schema.