Tool Directory / ORMs
Decide how much SQL you want to write yourself
The data access layer is a spectrum, not a binary. At one end an ORM hides SQL behind objects; at the other you write queries by hand and map the rows. Every option below sits somewhere on that line, and the right spot depends on how much your team enjoys SQL.
Reviewed August 2026. Back to the tool directory.
What this layer decides
Three practical consequences. Debuggability: when a query is slow, can you look at your code and predict the SQL, or do you have to turn on query logging to find out? Runtime fit: does it run on Cloudflare Workers and other edge environments, or does it need a Node process? Migrations: is there a real story for evolving the schema, or are you writing SQL files by hand anyway?
Notably, the type-safety argument is over. Every serious option in 2026 gives you compile-time checking of column names and result shapes. What still separates them is how much sits between the code you write and the query the database receives.
The four positions on the spectrum
Prisma
7.x - the Rust engine is gone
Prisma 7 dropped the Rust query engine for a pure TypeScript implementation, cutting bundle size dramatically and improving cold starts by roughly an order of magnitude. That single change removed the main reason people left. You still get the best migration tooling in the ecosystem, a readable schema file, and Prisma Studio for browsing data. The schema DSL is still a separate language you have to learn. prisma.io
Drizzle
1.x - SQL you can predict
Schemas are TypeScript files, queries read like SQL, and there is no code generation step between writing and running. It weighs a few kilobytes, has zero dependencies, and runs on every edge runtime without a proxy. Drizzle Kit handles migrations competently. The tradeoff is that you write more query code by hand and the docs assume you already know SQL joins. orm.drizzle.team
Kysely
A query builder, not an ORM
Type-safe SQL with autocomplete on table and column names, and essentially nothing else. No entity mapping, no lazy loading, no relation graph - you write SQL structure in TypeScript and get typed rows back. The thinnest abstraction that still catches typos at compile time. Bring your own migration tooling, or generate types from an existing database and go. kysely.dev
Raw SQL
Underrated for small surfaces
A driver such as postgres.js or better-sqlite3, tagged template literals for parameterized queries, and plain .sql files for migrations. Zero abstraction cost, zero upgrade treadmill, and the query in your editor is byte-for-byte the query the database runs. Below about thirty tables this is frequently the correct answer, and the skill transfers to every language you will ever use. postgres.js
Three traps that outlive your tool choice
The N+1 query
Every ORM makes it trivially easy to loop over rows and fire one query per iteration. It looks fine on a hundred seed records and falls over at ten thousand. Log query counts per request in development and set an alarm on the number, not on latency.
Connection pooling on serverless
Serverless functions scale to hundreds of instances, each wanting its own database connection, and Postgres runs out long before your traffic does. Use a pooler such as PgBouncer, Supavisor, or your provider's built-in equivalent from the first deploy.
Migrations without a rollback
Generated migrations are only useful if you have run them backwards at least once. Test the down path in staging, and never combine a destructive column drop with a deploy in the same step - ship the code first, drop the column a release later.
Our pick
Drizzle for new TypeScript projects
Use Drizzle. Schemas are plain TypeScript, queries look enough like SQL that you can reason about performance without enabling query logging, it runs on every edge runtime without a proxy service, and there is no generate step to forget before a build. The learning curve is real if your team does not know SQL, and that curve is worth climbing anyway.
Prisma 7 is a genuinely good product again and the right pick when migration tooling and onboarding speed matter more than SQL transparency. Kysely wins when you want types and nothing else. And if the application has fewer than about thirty tables, writing the SQL yourself is not a step backwards - it is one fewer dependency with a major version to chase.
Keep going
Prisma vs Drizzle
The closest race in the data layer, decided on specifics.
Read the verdictSQL cheatsheet
Joins, aggregates, and indexes - useful whichever tool wins.
Grab the cheatsheetDatabase layer
Pick the engine before you pick the thing that queries it.
Browse the layerAPI stack guide
A complete backend with the data layer already chosen.
See the stackThe runtime you deploy on constrains this choice more than anything else - see backend runtimes and frameworks and hosting platforms before committing to a tool that needs a long-lived Node process.