DEV Community

Cover image for The Problem No One Talks About in Prisma APIs
Manan Kanani
Manan Kanani

Posted on

The Problem No One Talks About in Prisma APIs

Prisma has made SQL database access in Node.js incredibly clean.

Schemas are readable.
Type safety is excellent.
Queries feel intuitive.

But after building a few real-world APIs with Prisma, I ran into a problem that no one really talks about.

Not performance.
Not migrations.
Not relations.

Repetitive query logic.
And once you see it, you can’t unsee it.


The Part Everyone Accidentally Rebuilds

Every Prisma API starts the same way.

A simple findMany.
A couple of filters.
One search field.

Then requirements grow.

Now the endpoint needs:

  • filtering
  • searching
  • sorting
  • pagination
  • soft delete checks
  • query validation

So you add a few if statements.
You write something like this in one service:

if (query.isActive) {
  where.isActive = query.isActive === "true";
}

if (query.search) {
  where.OR = [
    { firstName: { contains: query.search, mode: "insensitive" } },
    { email: { contains: query.search, mode: "insensitive" } }
  ];
}

if (query.sort === "createdAt") {
  orderBy.createdAt = "desc";
}
Enter fullscreen mode Exit fullscreen mode

And suddenly every endpoint has its own slightly different version of the same logic.

Not because you planned it that way - but because Prisma doesn't give you an opinion here.


Copy-Paste Is Easy. Living With It Isn’t.

At first, duplication feels fine.

But over time:

  • one endpoint allows invalid filters
  • another rejects them
  • one sorts on any column
  • another breaks if you try
  • one handles booleans correctly
  • another treats everything as a string

Nothing is technically broken.
But nothing feels solid either.

This is how small inconsistencies turn into long debugging sessions.


Helpers Don’t Actually Fix This

The obvious move is a helper function.

Most teams try it.
Most teams regret it.

Helpers tend to become:

  • too flexible to be safe
  • too strict to be reusable
  • hard to reason about
  • impossible to extend cleanly

And many of them go one step too far — they run the Prisma query for you.

That’s when your service layer starts losing control.


The Shift That Changed Everything

Instead of asking:

“How do I share this logic?”

I asked:

“Why is this logic even being written repeatedly?”

Every endpoint already knows its rules:

  • what can be filtered
  • what can be searched
  • what can be sorted
  • what should be rejected

So the real problem wasn’t queries.

It was encoding intent.


Declare Rules. Get a Prisma Query.

That idea became Prisma Query Builder (prisma-qb).

Instead of hand-writing query logic, you configure rules:

import { buildPrismaQuery } from "prisma-qb";

const { where, orderBy } = buildPrismaQuery({
  query: req.query,
  searchFields: [
    { field: "firstName" },
    { field: "email" }
  ],
  filterFields: [
    { key: "isActive", field: "isActive", type: "boolean" }
  ],
  sortFields: [
    { key: "createdAt", field: "createdAt" }
  ],
  defaultSort: { key: "createdAt", order: "desc" }
});
Enter fullscreen mode Exit fullscreen mode

What comes out is not data — just a safe Prisma query object.

  • A Prisma where
  • A Prisma orderBy

No execution.
No abstraction.
No opinion about how you fetch.

Your service stays boring — in the best way.


Strict by Default (And That’s the Point)

Most bugs here don’t come from bad code.

They come from:

  • unexpected query params
  • invalid filters
  • unchecked sorts

Prisma Query Builder blocks those immediately.

Not silently.
Not later.
Immediately.

The API becomes predictable — not just for users, but for developers too.


Search That Doesn’t Break Your API

Search is where most APIs quietly fail.

Numbers get treated like strings.
Booleans behave unpredictably.
One bad field breaks the whole query.

Here, search is type-aware.

Valid fields participate.
Invalid ones are skipped safely.
Nothing crashes.
Nothing leaks through.

Your API stays stable even with messy input.


This Isn’t a Prisma Replacement

It doesn’t:

  • wrap Prisma
  • hide Prisma
  • execute Prisma
  • invent new query concepts

It simply builds Prisma queries responsibly.

You still own the data.
You still own the execution.
You still own the architecture.


Who This Is For

This is for people who:

  • build real APIs, not demos
  • care about long-term consistency
  • hate rewriting the same logic
  • want services that stay readable over time

If that sounds familiar, you’ve already felt this problem.


Final Thought

Prisma solved database access.

But API-level query handling is still left to repetition, habits, and copy-paste.

Prisma Query Builder exists to remove that noise.

And once it’s gone,
your API feels calmer — and stays that way.

🔗 npm

https://www.npmjs.com/package/prisma-qb

If you try it and hate it, tell me.
If you like it, tell me.

Either way — that’s how better tools get built 😉

Top comments (0)