The concept map for a Node app on Drizzle ORM — Express, Fastify, Hono or Next.js route handlers in
front. The runbook — phases, exit conditions, stop conditions — is
Migrating an existing app; this page says what each term becomes.
As of 2026-11 (orm.drizzle.team).
Concept map
| Node / Drizzle | Ultimate |
|---|
| an Express / Fastify / Hono route that renders | a route file: Routes and render modes |
| a route handler that writes, a tRPC mutation | an action: Actions |
| a tRPC query, a GET handler | a query: Queries and live queries |
a pgTable() declaration | an entity(): Entities and migrations |
drizzle-kit generate, migrate | x db gen "<name>", then x db migrate |
| a Zod schema on a handler | the action's input: Actions |
| BullMQ, pg-boss | a job: Jobs and workflows |
node-cron, a repeatable job | a task: Scheduled tasks |
| Passport, Auth.js, Lucia | Auth |
| CASL, hand-written middleware checks | a policy: Policies and authz |
Socket.IO, ws | a live query: Realtime |
| Nodemailer | Mail |
| S3 SDK calls | Storage and uploads |
| Vitest, Jest | bun test through Testing |
node server.js, next dev | x dev |
What does not map
| Node / Drizzle | Why |
|---|
| Node-only APIs and native addons | Bun only: check each against Bun's own list, bun.sh/docs/runtime/nodejs-apis |
MySQL, SQLite (mysqlTable, sqliteTable) | Postgres only, by design: Home |
| React components | pages render with SolidJS; interactive parts are islands. No converter |
| a serverless or edge deploy target | containers only: Deployment |
Schema adoption
Drizzle already declares tables in TypeScript, so the shape carries over column by column; ids are
whatever the app chose. Phase 1 of the runbook declares the existing tables with the physical-name
overrides and type map it gives, then x db gen until x verify --only drift agrees:
Migrating an existing app.
Identity cutover
| The app stores | Branch |
|---|
bcrypt / bcryptjs hashes ($2a$, $2b$) | proceed: verified natively, rewritten as argon2id on first login (Migrating an existing app) |
argon2 hashes ($argon2id$) | proceed: rehashed when weaker than the policy |
| scrypt, PBKDF2, anything else | ⛔ stop: no verifier ships. Keep the old login as a bridge, or force a reset |
| a JWT or a session table | bridge it with your own verifier behind configureAuthenticator() (Auth) |