The Setup
I've used Prisma extensively since 2024. It's a solid ORM with great developer experience — the schema language is intuitive, migrations are well-designed, and the type generation is excellent.
But over time, I ran into friction points that made me reconsider whether a traditional ORM was the right default for every project.
What Bothered Me
Schema Coupling
Every database interaction goes through the Prisma client, which means your entire application is tightly coupled to your Prisma schema. Want to add a computed field? You need to extend the model. Want a different shape for a specific query? You're decorating the base type.
Query Performance
The generated queries are often suboptimal. I found myself writing raw SQL for anything performance-sensitive, which defeats the purpose of an ORM:
// Prisma — N+1 risk, unpredictable SQL
const users = await prisma.user.findMany({
include: { posts: { where: { published: true } } },
});
// Raw SQL — exact control, predictable performance
const users = await prisma.$queryRaw`
SELECT u.*, COUNT(p.id) as post_count
FROM users u
LEFT JOIN posts p ON p.author_id = u.id AND p.published = true
GROUP BY u.id
`;
When you're writing raw SQL for the important queries, the ORM is mostly decorative overhead.
Migration Fragility
Migrations work well for simple schema changes. But for anything involving data transformations — renaming columns, splitting tables, restructuring relations — the migration system gets brittle fast.
What I Use Now
For most new projects, I use Drizzle ORM with direct SQL for complex queries. The approach is:
- Drizzle for schema definition, migrations, and simple CRUD
- Direct SQL (via
postgres.jsorpg) for anything complex - Zod schemas for runtime validation (not the ORM layer)
This gives me the best of both worlds: type-safe schema management when I need it, and raw SQL performance when it matters.
When Prisma Still Makes Sense
I'm not saying Prisma is bad. It's excellent for:
- Prototyping and MVPs where speed matters more than optimization
- Teams that want strong opinions enforced by the ORM
- Projects with relatively simple data models
But for production applications with complex queries and evolving schemas, the flexibility of a lighter ORM plus raw SQL is hard to beat.
The Takeaway
Don't default to any tool. Choose based on your project's actual needs, not your familiarity with a particular stack. The best tool is the one that matches the complexity of your problem.