Skip to content

web: Switch from SQLite to PostgreSQL#7

Merged
tomjnsn merged 1 commit intomainfrom
postgres/core-migration
Feb 17, 2026
Merged

web: Switch from SQLite to PostgreSQL#7
tomjnsn merged 1 commit intomainfrom
postgres/core-migration

Conversation

@tomjnsn
Copy link
Copy Markdown
Owner

@tomjnsn tomjnsn commented Feb 17, 2026

Summary

  • Switch all 13 Drizzle tables from sqliteTable() to pgTable() with proper column type mappings (boolean, timestamp, doublePrecision)
  • Replace better-sqlite3 + drizzle-orm/better-sqlite3 with postgres + drizzle-orm/postgres-js
  • Port all SQLite-specific SQL (DATE(col,'unixepoch'), STRFTIME, PRAGMA, raw prepared statements) to PostgreSQL equivalents
  • Rewrite migration runner to use Drizzle's built-in postgres migrator, generate fresh Postgres baseline migration

Closes #1, closes #2, closes #3, closes #4

Test plan

  • bun run check passes (format, lint, type check)
  • Spin up local Postgres, run bun run --filter packages/web db:migrate — applies cleanly
  • bun run --filter packages/web dev — app starts, can login, create transcripts
  • Verify date charts (daily activity, team activity by user)
  • Verify blob access control (view transcript screenshots)

🤖 Generated with Claude Code

Schema (closes #1):
- All 13 tables: sqliteTable() → pgTable()
- integer({mode:

🔮 View transcript: https://agentlogs.chsprc.com/s/bwgzcefdb8jizsaurae83j2s"boolean"}) → boolean()
- integer({mode:"timestamp"}) → timestamp({withTimezone, mode:"date"})
- real() → doublePrecision()
- .default(sql`unixepoch(...)`) → .defaultNow()
- Move better-sqlite3 from deps to devDeps, add postgres

Driver & config (closes #2):
- db/index.ts: better-sqlite3 → postgres.js, DB_PATH → DATABASE_URL
- drizzle.config.ts: dialect sqlite → postgresql
- auth.ts: provider sqlite → pg

Queries (closes #3):
- DATE(col,'unixepoch') → col::date
- STRFTIME → TO_CHAR for hourly grouping
- Remove Math.floor(ms/1000) unix conversions, pass Date objects
- db.$client.prepare().get() → await db.execute(sql`...`)
- Remove PRAGMA foreign_keys = ON

Migration runner (closes #4):
- Rewrite migrate.mjs to use Drizzle's built-in postgres migrator
- Delete old SQLite migrations, generate fresh Postgres baseline

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tomjnsn tomjnsn merged commit 8230430 into main Feb 17, 2026
0 of 3 checks passed
@tomjnsn tomjnsn deleted the postgres/core-migration branch February 17, 2026 18:25
tomjnsn added a commit that referenced this pull request Feb 24, 2026
Schema (closes #1):
- All 13 tables: sqliteTable() → pgTable()
- integer({mode:

🔮 View transcript: https://agentlogs.chsprc.com/s/bwgzcefdb8jizsaurae83j2s"boolean"}) → boolean()
- integer({mode:"timestamp"}) → timestamp({withTimezone, mode:"date"})
- real() → doublePrecision()
- .default(sql`unixepoch(...)`) → .defaultNow()
- Move better-sqlite3 from deps to devDeps, add postgres

Driver & config (closes #2):
- db/index.ts: better-sqlite3 → postgres.js, DB_PATH → DATABASE_URL
- drizzle.config.ts: dialect sqlite → postgresql
- auth.ts: provider sqlite → pg

Queries (closes #3):
- DATE(col,'unixepoch') → col::date
- STRFTIME → TO_CHAR for hourly grouping
- Remove Math.floor(ms/1000) unix conversions, pass Date objects
- db.$client.prepare().get() → await db.execute(sql`...`)
- Remove PRAGMA foreign_keys = ON

Migration runner (closes #4):
- Rewrite migrate.mjs to use Drizzle's built-in postgres migrator
- Delete old SQLite migrations, generate fresh Postgres baseline

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant