See every query your Prisma app makes.
The database profiler for Prisma ORM, in development. Every SQL statement of a request, the line of your code that sent it, and a warning the moment an N+1 shows up.
app/routes/home.tsx:8↓ The bar at the bottom of this page is the real one, on the same sample data. Click it.
One line per request in your terminal, too.
An ORM hides the SQL. We show it back.
Prisma turns one line of TypeScript into several statements, and a loop into a hundred. You find out in production. query-profiler opens a profile for every request in development, records each operation and the SQL it ran, and tells you which line to look at.
The Warnings tab, before your users find it
- N+1Queries in a loop. The same statement shape five times or more, collapsed into one row with its count.
≥ 5 same shape - SLOWSlow statements. Marked in the list and on the timeline, next to the time the database was really busy.
≥ 100 ms - DUPLICATEWork done twice. The exact query, same parameters, more than once in a request.
same SQL + params - ORIGINThe line that sent it. Every operation points at your file and line, one click from your editor.
file:line - CALLSA page and its calls. Fetchers, actions and navigations hang under the page that made them.
X-Debug-Parent - SAFESecrets stay hidden. Passwords and tokens never show, in the arguments or in the SQL parameters.
[redacted]
Two lines, nothing to remove
Add the Vite plugin and wrap your Prisma client. Nothing goes in your routes, and production builds get empty versions of both, so there is no if (DEV) anywhere.
import { PrismaPg } from "@prisma/adapter-pg"; import { profilePrisma, withProfiler } from "query-profiler/prisma"; const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }); export const prisma = profilePrisma( new PrismaClient(withProfiler({ adapter })), );
import { reactRouter } from "@react-router/dev/vite"; import { queryProfiler } from "query-profiler/vite"; export default defineConfig({ plugins: [queryProfiler({ log: true }), reactRouter()], });
Room to read it, at /_profiler
Every recent request with its calls under it, the one you pick with its cards and tabs, and stats across all of them: the slowest statements, the most repeated, time by model and by route.
/productsdocument · 1 query · 1.88 ms/products/offersdata · 2 queries · 3.46 ms/products/purchasesdata · 2 queries · 1.84 ms/document · 7 queries · 1 warningPrisma first. Your framework next.
- Prisma ORM7.1+
- PostgreSQL—
- MySQL · MariaDB—
- SQLite—
- React Router7.9+ · 8 · Remix
- Vite6+
- Express4.18+ · 5
- Fastify4.26+ · 5
- NestJS12
- Koa3
- Hapi21
- Hono4 on Node