Skip to content

Commit 8df6e3d

Browse files
committed
fix(db): always run migrations on boot; drop AUTO_MIGRATE gate
Removes the AUTO_MIGRATE / NODE_ENV gate on TypeORM migrationsRun and makes migrations run unconditionally on every boot. The gate was a relic of when the same config served dev / test / prod with different needs; with synchronize permanently false, committed migrations are the only path for schema changes and there's no production scenario where booting with pending migrations is correct. 5.45.1 shipped this gate without honoring AUTO_MIGRATE, so fresh production installs only got Better Auth's 4 tables — the dashboard 500'd on missing user_providers / notification_rules. The fix landed in fc7890f and is in 5.46.0+, but pinning behavior to an env var that compose must set is a footgun: a future env-var typo would silently re-introduce the bug. Promoting the default removes the class of mistake. Compose and the docker run examples drop the AUTO_MIGRATE=true line since it's now redundant. The autoMigrate config field and its three spec tests are removed — nothing in production code reads them. Companion to the Phase 3 hardening pass (#1551 / #1557).
1 parent 3b9c719 commit 8df6e3d

File tree

6 files changed

+8
-28
lines changed

6 files changed

+8
-28
lines changed

docker/DOCKER_README.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ docker run -d \
130130
-e DATABASE_URL=postgresql://user:pass@host:5432/manifest \
131131
-e BETTER_AUTH_SECRET=$(openssl rand -hex 32) \
132132
-e BETTER_AUTH_URL=http://localhost:3001 \
133-
-e AUTO_MIGRATE=true \
134133
manifestdotbuild/manifest
135134
```
136135

@@ -147,7 +146,6 @@ docker run -d `
147146
-e DATABASE_URL=postgresql://user:pass@host:5432/manifest `
148147
-e BETTER_AUTH_SECRET=$secret `
149148
-e BETTER_AUTH_URL=http://localhost:3001 `
150-
-e AUTO_MIGRATE=true `
151149
manifestdotbuild/manifest
152150
```
153151

@@ -164,13 +162,12 @@ docker run -d ^
164162
-e DATABASE_URL=postgresql://user:pass@host:5432/manifest ^
165163
-e BETTER_AUTH_SECRET=<your-64-char-secret> ^
166164
-e BETTER_AUTH_URL=http://localhost:3001 ^
167-
-e AUTO_MIGRATE=true ^
168165
manifestdotbuild/manifest
169166
```
170167

171168
</details>
172169

173-
`AUTO_MIGRATE=true` runs TypeORM migrations on first boot. Then visit [http://localhost:3001](http://localhost:3001) and complete the setup wizard to create your admin account.
170+
TypeORM migrations run automatically on every boot — fresh installs come up with the schema in place. Then visit [http://localhost:3001](http://localhost:3001) and complete the setup wizard to create your admin account.
174171

175172
### Verifying the image signature
176173

docker/docker-compose.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ services:
3232
- BETTER_AUTH_URL=${BETTER_AUTH_URL:-http://localhost:3001}
3333
- SEED_DATA=false
3434
- NODE_ENV=production
35-
- AUTO_MIGRATE=true
3635
# Email provider (optional). Covers both login/verification emails
3736
# and threshold alert notifications. Set one provider block — see
3837
# DOCKER_README.md "Email setup". Supports resend, mailgun, sendgrid.

packages/backend/.env.example

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ BETTER_AUTH_URL=http://localhost:3001
1212
# FRONTEND_PORT= # Extra trusted origin port for Better Auth
1313

1414
# ── Database ─────────────────────────────────────────
15-
# AUTO_MIGRATE=true # Run TypeORM migrations on startup (dev/test auto-run; set true for self-hosted prod first boot)
1615
# DB_POOL_MAX=20 # PostgreSQL connection pool size (default: 20)
1716

1817
# ── Rate Limiting ────────────────────────────────────

packages/backend/src/config/app.config.spec.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -86,24 +86,6 @@ describe('appConfig', () => {
8686
expect(config.databaseUrl).toContain('postgresql://');
8787
});
8888

89-
it('defaults autoMigrate to false', async () => {
90-
delete process.env['AUTO_MIGRATE'];
91-
const config = await loadConfig();
92-
expect(config.autoMigrate).toBe(false);
93-
});
94-
95-
it('reads AUTO_MIGRATE=true from env', async () => {
96-
process.env['AUTO_MIGRATE'] = 'true';
97-
const config = await loadConfig();
98-
expect(config.autoMigrate).toBe(true);
99-
});
100-
101-
it('ignores non-true AUTO_MIGRATE values', async () => {
102-
process.env['AUTO_MIGRATE'] = '1';
103-
const config = await loadConfig();
104-
expect(config.autoMigrate).toBe(false);
105-
});
106-
10789
it('reads EMAIL_PROVIDER from env', async () => {
10890
process.env['EMAIL_PROVIDER'] = 'resend';
10991
const config = await loadConfig();

packages/backend/src/config/app.config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ export const appConfig = registerAs('app', () => ({
1212
port: Number(process.env['PORT'] ?? 3001),
1313
nodeEnv: process.env['NODE_ENV'] ?? 'development',
1414
databaseUrl: resolveDatabaseUrl(),
15-
autoMigrate: process.env['AUTO_MIGRATE'] === 'true',
1615

1716
corsOrigin: process.env['CORS_ORIGIN'] ?? 'http://localhost:3000',
1817
betterAuthUrl: process.env['BETTER_AUTH_URL'] ?? '',

packages/backend/src/database/database.module.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,13 @@ const migrations = [
149149
url: config.get<string>('app.databaseUrl'),
150150
entities,
151151
synchronize: false,
152-
migrationsRun:
153-
process.env['AUTO_MIGRATE'] === 'true' ||
154-
['development', 'test'].includes(config.get<string>('app.nodeEnv') ?? ''),
152+
// Run migrations on every boot. `synchronize: false` is permanent, so
153+
// committed migrations are the only source of schema changes — there's
154+
// no scenario where production should boot with pending migrations
155+
// unapplied (the dashboard 500s on missing tables). Previously this
156+
// was gated on AUTO_MIGRATE=true / NODE_ENV, which broke fresh
157+
// production installs whose env didn't set the var (see #1551 / 5.45.1).
158+
migrationsRun: true,
155159
migrationsTransactionMode: 'all' as const,
156160
migrations,
157161
logging: false,

0 commit comments

Comments
 (0)