🚀 The Solution for Slow Prisma

Fix Slow Prisma Queries
With Direct SQL Execution

Love Prisma's DX but need lower read overhead on supported query shapes? Current benchmark JSON shows average speedups across Prisma v6, v7, and v8 for supported PostgreSQL and SQLite reads; individual query shapes vary.

Faster Supported Reads
No Query Changes
Current Benchmark JSON
PostgreSQL & SQLite
Fix slow Prisma in one line
import { PrismaClient, Prisma } from '@prisma/client'
import { speedExtension, convertDMMFToModels } from 'prisma-sql'
import postgres from 'postgres'

const sql = postgres(process.env.DATABASE_URL)
const models = convertDMMFToModels(Prisma.dmmf.datamodel)

const prisma = new PrismaClient().$extends(
  speedExtension({ postgres: sql, models })
)

const users = await prisma.user.findMany({
  where: { status: 'ACTIVE' },
  include: { posts: true }
})
v6–v8
Prisma Coverage
PostgreSQL and SQLite benchmark matrix
0
Query Changes
Keep your existing Prisma calls
6
Benchmark Files
Prisma v6/v7/v8 × PG/SQLite
100%
Type Safety
Same Prisma API

Why Is Prisma Slow?

Understanding Prisma's evolution and performance characteristics helps explain why this extension exists.

The Prisma Journey: DX First, Performance Matters at Scale

🎯 2019: The Birth of Modern Prisma

Prisma 2 launched in 2019, changing the TypeScript ORM landscape with type-safe database access and generated types from your schema. Prisma introduced an engine-based architecture to translate queries, validate them, and provide strong guarantees that were hard to achieve with traditional JavaScript ORMs.

⚡ 2020–2022: Rapid Growth & Feature Expansion

Prisma added powerful features like nested writes, transactions, and middleware. The feature set expanded, but every query still paid an architectural cost: queries are represented, validated, executed, and results are shaped to match the Prisma API.

📊 2023: Overhead Becomes Noticeable at Scale

As more teams deployed Prisma in high-traffic workloads, the fixed per-query overhead became measurable. This is most visible on read-heavy endpoints, analytics, aggregations, and large result sets. The overhead is not a bug; it's the cost of Prisma’s guarantees and API behavior.

🚀 2024–2025: Prisma Performance Work Continues

Prisma shipped major updates focused on performance and engine changes. Even with improvements, there is still an unavoidable cost to parsing, validating, planning, and shaping results compared to executing raw SQL directly.

🎯 2026: prisma-sql Extension Released

This extension focuses on read performance. It bypasses Prisma’s read execution path for findMany, findFirst, findUnique, count, aggregate, and groupBy, while keeping Prisma for writes, migrations, schema management, and type generation. Validate compatibility with your Prisma version before rollout.

💡 Why This Extension Exists

Prisma made the right architectural choices for its goals: type safety, developer experience, and cross-database behavior. But those choices create overhead that's noticeable at scale. This extension doesn't replace Prisma—it optimizes reads for teams that want Prisma's DX plus faster execution where it matters.

Query Translation Layer

Prisma translates your query inputs into database-specific SQL. This enables cross-database behavior and Prisma's API semantics, but adds processing time before the database sees the SQL.

Validation & Type Guarantees

Prisma validates queries against the schema and enforces API-level guarantees. These safeguards prevent classes of bugs, but they also add overhead to each query.

Result Shaping

Results are shaped to match Prisma's API behavior. This is great for DX and consistency, but it adds latency, especially on large result sets and complex includes.

This extension complements Prisma by offering a faster path for supported read queries. You keep Prisma for schema, migrations, writes, and generated types while generated SQL handles selected hot reads through database-native clients.

How Much Faster? Real Benchmarks

Latest benchmark JSON comparison across Prisma v6, v7, v8, Drizzle ORM, and prisma-sql

PostgreSQL

3 latest version runs • 95 query cases per run

Prisma v6 (6.19.3)
benchmark-results/v6-postgres-latest.json
1.82× vs Prisma
1.47× vs Drizzle
95 measured query cases Aug 27, 2026
Prisma v7 (7.10.0)
benchmark-results/v7-postgres-latest.json
1.32× vs Prisma
1.28× vs Drizzle
95 measured query cases Aug 27, 2026
Prisma v8 (8.1.0-dev.1)
benchmark-results/v8-postgres-latest.json
1.31× vs Prisma
1.14× vs Drizzle
95 measured query cases Aug 27, 2026
Best current average: 1.82× vs Prisma in Prisma v6 (6.19.3)

SQLite

3 latest version runs • 83 query cases per run

Prisma v6 (6.19.3)
benchmark-results/v6-sqlite-latest.json
4.79× vs Prisma
1.71× vs Drizzle
83 measured query cases Aug 27, 2026
Prisma v7 (7.10.0)
benchmark-results/v7-sqlite-latest.json
2.23× vs Prisma
1.99× vs Drizzle
83 measured query cases Aug 27, 2026
Prisma v8 (8.1.0-dev.1)
benchmark-results/v8-sqlite-latest.json
2.15× vs Prisma
1.75× vs Drizzle
83 measured query cases Aug 27, 2026
Best current average: 4.79× vs Prisma in Prisma v6 (6.19.3)

Generated from 6 latest benchmark JSON files in this checkout. The detailed table below uses the same data, a 1ms practical-significance threshold, and separate runtime/prerendered methodology. View detailed benchmark table → View complete benchmark data →

Detailed Benchmark Results

Statistical comparison with Welch's t-test and a 1ms practical significance threshold

These results reflect runtime mode, where queries are converted to SQL on each request. In prerendered mode, SQL is generated at build time — runtime executes raw parameterized queries with zero conversion overhead.

PostgreSQL Prisma v6 (6.19.3)

Avg 1.82x vs Prisma Avg 1.47x vs Drizzle 24/95 significant wins 70 within noise floor
Aug 27, 2026
Test Prisma prisma-sql Drizzle Speedup Sig. CV% n
findMany basic 0.519ms ±0.023 0.233ms ±0.012 1.42ms ~1.00x 18.5% 50
findMany where = 0.614ms ±0.022 0.577ms ±0.065 0.444ms ~1.00x 40.4% 50
findMany where >= 16.16ms ±0.370 4.77ms ±0.364 6.19ms 3.39x 1.30x D *** 27.5% 50
findMany where IN 0.588ms ±0.019 0.314ms ±0.012 0.411ms ~1.00x 14.2% 50
findMany where null 0.266ms ±0.0097 0.141ms ±0.0050 0.188ms ~1.00x 13.0% 50
findMany ILIKE 0.208ms ±0.0089 0.221ms ±0.011 0.159ms ~1.00x 17.5% 50
findMany AND 2.94ms ±0.081 0.951ms ±0.096 2.13ms 3.09x 2.24x D *** 36.4% 50
findMany OR 16.23ms ±4.17 4.44ms ±0.470 5.47ms 3.66x 1.23x D *** 38.2% 50
findMany NOT 0.606ms ±0.022 0.385ms ±0.029 0.374ms ~1.00x 27.0% 50
findMany orderBy 1.85ms ±0.077 1.19ms ±0.228 0.730ms ~1.00x 69.2% 50
findMany pagination 0.223ms ±0.011 0.211ms ±0.012 0.369ms ~1.00x 20.6% 50
findMany select 0.248ms ±0.014 0.137ms ±0.0042 0.099ms ~1.00x 10.9% 50
findMany relation some 0.869ms ±0.016 0.451ms ±0.0061 ~1.00x 4.8% 50
findMany relation every 0.714ms ±0.023 0.501ms ±0.013 ~1.00x 9.6% 50
findMany relation none 29.48ms ±1.51 9.80ms ±1.02 3.01x *** 16.8% 10
findMany nested relation 1.52ms ±0.051 1.25ms ±0.065 ~1.00x 18.8% 50
findMany complex 2.25ms ±0.092 1.28ms ±0.229 1.28ms ~1.00x 64.8% 50
findFirst 0.841ms ±0.143 0.281ms ±0.033 0.399ms ~1.00x 42.1% 50
findFirst skip 0.449ms ±0.200 0.198ms ±0.011 0.491ms ~1.00x 19.6% 50
findUnique id 0.412ms ±0.102 0.289ms ±0.036 0.247ms ~1.00x 44.8% 50
findUnique email 0.373ms ±0.114 0.299ms ±0.080 0.217ms ~1.00x 97.1% 50
count 0.136ms ±0.0083 0.095ms ±0.011 0.104ms ~1.00x 40.8% 50
count where 1.17ms ±0.063 0.735ms ±0.027 0.457ms ~1.00x 13.3% 50
aggregate count 0.248ms ±0.0042 0.192ms ±0.0033 ~1.00x 6.2% 50
aggregate sum/avg 0.335ms ±0.0044 0.272ms ±0.0028 ~1.00x 3.7% 50
aggregate where 0.471ms ±0.016 0.319ms ±0.012 ~1.00x 14.1% 50
aggregate min/max 0.349ms ±0.019 0.284ms ±0.0039 ~1.00x 4.8% 50
aggregate complete 0.426ms ±0.0055 0.324ms ±0.0028 ~1.00x 3.1% 50
groupBy 0.475ms ±0.038 0.414ms ±0.049 ~1.00x 43.0% 50
groupBy count 0.467ms ±0.017 1.17ms ±0.542 ~1.00x 167.5% 50
groupBy multi 0.634ms ±0.034 0.464ms ±0.012 ~1.00x 9.1% 50
groupBy having 0.567ms ±0.028 0.609ms ±0.072 ~1.00x 42.8% 50
groupBy + where 0.555ms ±0.017 0.382ms ±0.012 ~1.00x 11.4% 50
_count via include 0.676ms ±0.024 0.716ms ±0.091 ~1.00x 45.6% 50
_count via include + relations 1.53ms ±0.030 1.37ms ±0.028 ~1.00x 7.5% 50
groupBy aggregates 0.550ms ±0.024 0.627ms ±0.074 ~1.00x 42.4% 50
groupBy min/max 0.570ms ±0.047 0.418ms ±0.0036 ~1.00x 3.0% 50
include list + nested to-one 1.50ms ±0.037 0.481ms ±0.056 3.12x *** 42.2% 50
include list + nullable to-one 2.49ms ±0.042 1.68ms ±0.179 ~1.00x 38.6% 50
include posts 3.82ms ±0.187 1.04ms ±0.010 5.11ms 3.68x 4.91x D *** 3.5% 50
include profile 0.519ms ±0.022 0.476ms ±0.025 0.496ms ~1.00x 18.7% 50
include 3 levels 1.71ms ±0.025 1.85ms ±0.203 2.05ms ~1.00x 39.4% 50
include 4 levels 2.27ms ±0.090 1.69ms ±0.106 3.04ms ~1.00x 22.6% 50
include + where 2.26ms ±0.081 1.63ms ±0.087 4.25ms ~1.00x 19.4% 50
include + select nested 3.66ms ±0.134 1.94ms ±0.058 5.09ms 1.89x 2.63x D *** 10.8% 50
findMany startsWith 0.296ms ±0.118 0.219ms ±0.027 0.201ms ~1.00x 44.7% 50
findMany endsWith 0.528ms ±0.012 0.288ms ±0.0067 0.328ms ~1.00x 8.4% 50
findMany NOT contains 0.644ms ±0.050 0.228ms ±0.012 0.347ms ~1.00x 19.5% 50
findMany LIKE 0.186ms ±0.0086 0.113ms ±0.0025 0.103ms ~1.00x 7.9% 50
findMany < 26.16ms ±0.559 6.09ms ±0.410 8.79ms 4.29x 1.44x D *** 24.3% 50
findMany <= 26.84ms ±0.550 5.84ms ±0.286 9.14ms 4.59x 1.56x D *** 17.7% 50
findMany > 14.99ms ±0.405 4.24ms ±0.290 6.41ms 3.54x 1.51x D *** 24.7% 50
findMany NOT IN 0.566ms ±0.019 0.360ms ±0.032 0.331ms ~1.00x 31.7% 50
findMany isNot null 0.554ms ±0.016 0.218ms ±0.0050 0.312ms ~1.00x 8.2% 50
orderBy multi-field 2.35ms ±0.116 0.851ms ±0.086 0.642ms 2.76x 0.75x D *** 36.5% 50
orderBy relation to-one 2.06ms ±0.029 1.63ms ±0.044 ~1.00x 9.8% 50
orderBy relation + scalar 2.03ms ±0.058 1.47ms ±0.025 ~1.00x 6.2% 50
orderBy nullable relation 1.85ms ±0.077 1.16ms ±0.012 ~1.00x 3.9% 50
orderBy deep relation 2.18ms ±0.058 1.62ms ±0.042 ~1.00x 9.4% 50
orderBy deep relation + scalar 2.54ms ±0.043 1.94ms ±0.033 ~1.00x 6.1% 50
distinct status 7.89ms ±0.080 1.77ms ±0.190 4.47x *** 38.8% 50
distinct multi 12.31ms ±0.244 2.46ms ±0.071 5.01x *** 10.4% 50
cursor composite tuple 1.58ms ±0.022 1.42ms ±0.169 ~1.00x 42.9% 50
cursor composite desc 1.77ms ±0.031 1.33ms ±0.011 ~1.00x 2.9% 50
cursor prefix of orderBy 1.65ms ±0.023 1.23ms ±0.0089 ~1.00x 2.6% 50
select + include 0.983ms ±0.025 0.979ms ±0.146 0.339ms ~1.00x 53.7% 50
_count relation 0.719ms ±0.014 0.579ms ±0.0094 ~1.00x 5.9% 50
_count multi-relation 0.233ms ±0.035 0.171ms ±0.0042 ~1.00x 9.0% 50
_count inside include 1.14ms ±0.017 1.20ms ±0.227 ~1.00x 68.5% 50
_count inside nested select 1.65ms ±0.018 1.47ms ±0.012 ~1.00x 2.9% 50
_count deep include 1.76ms ±0.025 1.21ms ±0.014 ~1.00x 4.2% 50
ILIKE special chars 0.219ms ±0.0064 0.192ms ±0.0075 ~1.00x 14.2% 50
LIKE case sensitive 0.216ms ±0.011 0.158ms ±0.0047 ~1.00x 10.7% 50
findMany Date range 0.352ms ±0.0075 0.182ms ±0.0042 0.245ms ~1.00x 8.2% 50
count Date range 0.463ms ±0.039 0.347ms ±0.0080 0.372ms ~1.00x 8.4% 50
findMany Date gte 0.334ms ±0.0072 0.172ms ±0.012 0.214ms ~1.00x 25.3% 50
depth-1 low-fan 0.369ms ±0.0075 0.215ms ±0.0053 ~1.00x 8.7% 50
depth-1 mid-fan 2.35ms ±0.108 0.927ms ±0.097 2.53x *** 37.8% 50
depth-1 high-fan 2.32ms ±0.125 0.967ms ±0.136 2.40x *** 50.7% 50
depth-1 wide 2.18ms ±0.096 0.882ms ±0.022 2.47x *** 8.9% 50
depth-1 unbound 39.90ms ±0.937 9.17ms ±0.533 4.35x *** 21.0% 50
depth-2 5.07ms ±0.263 3.43ms ±0.205 1.48x *** 21.5% 50
depth-2 paginated Project→tasks 2.28ms ±0.759 5.13ms ±1.45 0.44x ** 101.9% 50
depth-2 high-fan 4.46ms ±0.341 2.49ms ±0.455 1.79x *** 65.8% 50
depth-2 wide 4.65ms ±0.258 3.96ms ±0.192 ~1.00x 17.5% 50
depth-2 unbound 65.22ms ±3.66 21.68ms ±4.66 3.01x *** 34.7% 10
depth-3 unbound 16.11ms ±0.478 7.77ms ±0.395 2.07x *** 18.3% 50
depth-3 paginated 1.90ms ±0.208 2.39ms ±0.307 ~1.00x 46.3% 50
depth-4 unbound 9.10ms ±0.192 5.01ms ±0.315 1.82x *** 22.7% 50
depth-4 paginated 1.91ms ±0.049 1.94ms ±0.297 ~1.00x 55.4% 50
findFirst depth-2 2.12ms ±0.147 1.32ms ±0.253 ~1.00x 69.0% 50
findUnique depth-2 Project→tasks→comment 2.16ms ±0.113 2.11ms ±0.081 ~1.00x 13.9% 50
complex nested select 3.88ms ±0.236 3.47ms ±0.190 ~1.00x 19.8% 50
ultra deep query 14.80ms ±0.289 6.69ms ±0.325 2.21x *** 17.6% 50
transaction: (3 operations) 3.50ms ±0.589 1.43ms ±0.061 2.45x *** 15.4% 50
*** p < 0.001 ** p < 0.01 *  p < 0.05 ns not significant  within 1ms noise floor ± 95% CI CV% > 15% = high variance
Runtime mode benchmarked. Prerendered mode skips query-to-SQL conversion entirely at runtime — expect lower latency than shown here, especially for complex queries where conversion cost is proportionally higher.
1 test(s) with statistically significant regressions beyond the 1ms threshold.

Methodology

  • Reproduce with: npm run bench (BENCHMARK_JSON_OUTPUT=1 writes JSON). Results land in benchmark-results/summary-.json; v--latest.json feeds this page.
  • Every query runs against the same database for all clients: Prisma, prisma-sql, Drizzle. Per-test sample size is shown in the n column.
  • Reported per side: mean, median, stdDev, p95, p99, CV%. Significance uses Welch's t-test with a 1ms practical threshold; error bars are 95% CI.
  • Runtime mode measured: SQL is converted per request. Prerendered (@optimize) queries skip conversion entirely and are faster than shown.
  • Hardware and versions vary between runs - each JSON file carries its own timestamp. Compare runs from the same machine.

How It Optimizes Prisma

Bypass Prisma's read execution path while keeping Prisma's API and types

1

Intercept Prisma Queries

Extension catches read operations (findMany, findFirst, findUnique, count, aggregate, groupBy) before they execute

2

Generate Optimized SQL

Convert Prisma queries into fast, parameterized SQL with optimized JOINs

3

Execute Directly

Run queries through postgres.js or better-sqlite3, bypassing Prisma read overhead

4

Return Compatible Results

Results match Prisma's expected shape. Types, IntelliSense, and existing query code remain unchanged

const users = await prisma.user.findMany({
  where: { status: 'ACTIVE' },
  include: { posts: true }
})

// Direct SQL execution for reads
// Benchmarked around ~1.00ms on this workload
// Same Prisma query code

Why Choose This Prisma Extension?

Get raw SQL execution speed for reads while keeping Prisma's developer experience

Instant Prisma Speedup

One-time setup accelerates Prisma reads. No refactoring, no migration, no downtime.

Keep Your Prisma Types

Full TypeScript support maintained. Type inference, autocomplete, and compile-time safety preserved while accelerating reads.

Production-Tested Solution

Current parity tests validate supported reads across recent Prisma versions. Use it for production apps after checking compatibility with your Prisma version and workload.

Multiple Database Support

Optimize Prisma reads on PostgreSQL (including Neon, Supabase) and SQLite.

Pre-Compiled Option

Optional generator creates build-time SQL, reducing overhead to microseconds for your hottest queries.

Serverless Ready (Node Runtimes)

Works in serverless Node runtimes. Edge runtime support depends on runtime constraints and the driver you use.

Extras on top of Prisma's API

Beyond faster reads

prisma-sql adds capabilities Prisma Client does not have. Same types, same code style.

$batch

N dashboard queries, one round trip

Combine independent reads into a single PostgreSQL round trip. Typed object result, no Promise.all juggling.

const dash = await prisma.$batch((b) => ({
  users: b.user.count(),
  posts: b.post.findMany({ take: 10 }),
  stats: b.task.aggregate({ _count: true }),
}))

@optimize

Prebake your hottest queries

Annotate a model in schema.prisma. At generate time the exact SQL is baked; matching runtime shapes skip conversion completely.

/// @optimize {
///   "method": "findMany",
///   "query": {
///     "where": { "status": "$status" },
///     "take": "$take"
///   }
/// }
model User { ... }

Cardinality planner

Strategy chosen by data, not by guess

Collected relation stats drive strategy switching between flat joins, correlated subqueries and where-in segmented loading. Large child tables never trigger per-parent scans.

prisma-sql-collect-stats \
  --output dist/planner.generated.js \
  --prisma-client dist/client/index.js

When Prisma Performance Matters Most

Common scenarios where this extension makes a real difference

📊 Analytics & Reporting

Prisma aggregations and groupBy operations benefit significantly from direct SQL execution

  • 5× faster groupBy accelerates reports
  • Faster aggregate queries
  • Real-time metrics with lower latency

🚀 High-Traffic APIs

Per-query overhead compounds under load, especially on read-heavy endpoints

  • Lower API response times
  • Handle more requests per instance
  • Reduce infrastructure costs

☁️ Serverless Functions

Every millisecond matters in serverless: reduce read latency where it counts

  • Better p95/p99 on reads
  • Lower costs through faster reads
  • Faster reads without refactors

📱 Mobile Backends

Users notice latency: faster reads improve perceived UX immediately

  • Faster feed loading
  • Faster pagination
  • More responsive interactions

Optimize Prisma in 3 Steps

Accelerate Prisma reads in under 60 seconds

① Install the Prisma Extension

# PostgreSQL
npm install prisma-sql postgres

# SQLite
npm install prisma-sql better-sqlite3

② Add Extension to Prisma Client

import { PrismaClient, Prisma } from '@prisma/client'
import { speedExtension, convertDMMFToModels } from 'prisma-sql'
import postgres from 'postgres'

const sql = postgres(process.env.DATABASE_URL)
const models = convertDMMFToModels(Prisma.dmmf.datamodel)

const prisma = new PrismaClient().$extends(
  speedExtension({ postgres: sql, models })
)

③ Use Prisma Normally

const users = await prisma.user.findMany({
  where: { status: 'ACTIVE' },
  include: { posts: true }
})

Prisma Performance FAQ

Common questions about optimizing Prisma reads

Why does Prisma have overhead?

Prisma adds overhead because it implements API guarantees like schema-based validation, consistent query behavior, and result shaping. Those layers provide a great developer experience but cost time compared to executing raw SQL directly.

How do I optimize Prisma queries?

Optimize read-heavy Prisma workloads by adding this extension. It executes read operations via direct SQL using postgres.js or better-sqlite3 while keeping Prisma's API and types. Setup is a small initialization change and does not require refactoring your existing queries.

Is Prisma slower than raw SQL?

For many read workloads, yes. There is architectural overhead compared to raw SQL execution. This extension aims to keep Prisma's DX while reducing read latency by executing SQL directly.

Can I speed up Prisma without changing existing queries?

Yes. Add the extension once during Prisma Client initialization and keep your existing Prisma query code unchanged. Read operations run faster while your Prisma API, types, and schema remain the same.

Does this work in production?

Yes, it is designed for production use on supported read paths. Always verify compatibility with your Prisma version and run your own regression tests before rollout.

What causes slower Prisma aggregations?

Aggregations and groupBy often amplify fixed overhead (query processing and result shaping) and can involve larger intermediate result sets. This extension optimizes those reads by generating SQL directly, which typically reduces latency on aggregation-heavy endpoints.

Ready to Speed Up Prisma?

Check the current benchmark table for supported PostgreSQL and SQLite reads