Query performance comparison using a real-world multi-join query: conversations + contact_channels + contacts + workflows + checkouts + workflow_goals + messages.
1000 iterations, concurrency 10
| Avg | P50 | P95 | P99 | Min | Max | |
|---|---|---|---|---|---|---|
| Raw SQL | 4.4 ms | 3.8 ms | 9.8 ms | 17.7 ms | 0.8 ms | 22.5 ms |
| Drizzle | 11.1 ms | 10.9 ms | 17.0 ms | 28.6 ms | 3.0 ms | 64.4 ms |
| Prisma | 35.2 ms | 34.8 ms | 46.7 ms | 58.5 ms | 20.0 ms | 92.7 ms |
| Supabase | 55.5 ms | 56.1 ms | 69.5 ms | 103.2 ms | 27.6 ms | 128.4 ms |
Winner: Raw SQL (51.1 ms / 92.1% faster than Supabase)
| File | Role |
|---|---|
server.ts |
Express server exposing GET /prisma, GET /supabase, and GET /drizzle endpoints |
bench.ts |
Fires 1000 requests at each endpoint (10 concurrent), collects server-side timings, reports percentiles |
Both endpoints query the same PostgreSQL database, returning the latest 100 conversations with all related data.
# install
npm install
npx prisma generate --schema=./prisma
# configure .env
DATABASE_URL=postgresql://user:pass@localhost:5432/dbname
DATABASE_API_URL=http://localhost:8080
JWT_SECRET=your-jwt-secret
# run
npm run server # start the benchmark server
npm run bench # run the benchmark (server must be running)- Prisma - TypeScript ORM with
findMany+includefor joins - Drizzle - Lightweight TypeScript ORM with SQL-like query builder
- Supabase PostgREST - REST API over PostgreSQL with embedded select syntax
- Raw SQL - Direct queries via
postgres.js(tagged template literals) - Express - HTTP server
- tsx - TypeScript execution