Migrations & Seed
Migrations & Seed
The API uses raw SQL migrations (verified at packages/api/migrations/*.sql) executed in filename-sorted order. The migration runner is cmd/migrate (invoked by make db-migrate). The seeder (cmd/seed) inserts a small set of demo users, schemas, and trust framework rows for development. The ER diagram above shows the core Postgres schema produced by these migrations and seeded by cmd/seed.
14.6.1 Migration files (current as of v2.0)
Note on duplicate
006_prefixes: the runner sorts filenames; ties are broken alphabetically.006_data_access.sqlis applied before006_delegates_and_attributes.sql.
14.6.2 Running migrations
The migrator:
- Connects via the same env vars as the server (
DB_HOST,DB_PASS, …). - Ensures a
schema_migrationstable exists. - Reads
migrations/directory. - For each file not yet recorded, runs the SQL inside a transaction and records the filename in
schema_migrations. - Stops on first error (transaction rolled back).
Idempotency: migrations are NOT idempotent by themselves. Once applied, they cannot be re-run; you must write a new migration to alter previously applied schema.
14.6.3 Authoring a new migration
- Pick the next sequence number:
007_<short-name>.sql. - Always wrap DDL in
BEGIN; ... COMMIT;(the runner runs it inside a tx, but explicit is safer). - Add an inverse rollback migration in the same numbered pair if your runner supports
down/migrations. 4. AddCREATE INDEX CONCURRENTLYfor production-load tables — but be aware:CONCURRENTLYcannot run inside a transaction, so it requires a separate migration file with the directive-- migrate:run-in-tx false(or equivalent). 5. Test on a copy of production data before merging.
14.6.4 Seeding the database
The seeder (verified at packages/api/cmd/seed/main.go) creates:
- Demo users —
admin@ida.local(admin),issuer@example.com(issuer),verifier@example.com(verifier),alice@example.com(holder). - Demo schemas —
EmploymentVC,EducationDegreeVC,KYC_LightVC. - Demo trust framework rows — pre-trusts
issuer@example.comfor all schemas. - Sample DIDs and credentials for each demo user.
Pass --reset to wipe before seeding (destructive — dev only):
Production: never run the seeder on production. Use a one-off SQL script for the initial admin user only.
14.6.5 Backups before migrations
Always snapshot before applying a migration in production:
Store the dump in object storage and verify with pg_restore --list backup-pre-007.dump.