Summary
This postmortem analyzes why the Fastify demo app’s database migration step reports success but creates no tables, except for the schemaversion table. Although the environment variables and DB connection appear correct, the migration system behaves as if there are zero migration files to execute.
Root Cause
The root cause is that the Fastify demo app ships with no actual migration files.
The project uses Kysely for migrations, and the demo repository intentionally includes only the migration framework, not any schema‑defining migration scripts.
As a result:
- The migration runner initializes the schema version table (
schemaversion) - It finds no migration files in the migrations directory
- It prints “Migration completed!” because technically nothing failed
- No tables are created because no migration scripts exist
Why This Happens in Real Systems
This pattern is common in template or starter repositories:
- Demo apps often include scaffolding but no real schema
- Migration tools treat “no migrations” as a successful run
- Developers assume migrations exist because the command runs without errors
- Starter projects expect the user to write their own migrations
Real-World Impact
When teams encounter this issue in production‑like environments, it can cause:
- Empty databases even though migrations “succeeded”
- Confusion during onboarding when new engineers expect tables to appear
- Silent failures because migration tools do not warn about missing files
- Broken application startup when the app expects tables that don’t exist
Example or Code (if necessary and relevant)
Below is an example of what a minimal Kysely migration file might look like in the Fastify demo structure:
export async function up(db) {
await db.schema
.createTable('users')
.addColumn('id', 'serial', col => col.primaryKey())
.addColumn('email', 'varchar(255)', col => col.notNull())
.execute();
}
export async function down(db) {
await db.schema.dropTable('users').execute();
}
This is the type of file the migration runner expects to find.
How Senior Engineers Fix It
Experienced engineers resolve this quickly by:
- Inspecting the migrations directory to confirm whether migration files exist
- Checking the migration runner logs to see which files were detected
- Creating initial schema migrations when none are present
- Ensuring the migration path is correctly configured in the project’s config
- Verifying that the demo app intentionally ships without migrations
In the Fastify demo specifically, the fix is:
- Write your own migration files, because the demo repo does not include any
Why Juniors Miss It
Less experienced engineers often overlook this because:
- They assume demo apps include a complete schema
- They interpret “Migration completed!” as meaning tables were created
- They do not yet know that migration tools succeed even with zero work
- They expect automatic schema generation, which Kysely does not provide
A senior engineer can walk them through verifying the migration directory and understanding how migration frameworks behave when no scripts are present.
If you want, I can outline a clean initial migration structure for the Fastify demo so you can bootstrap your schema quickly.