Implementing Query Middleware
Note: Classic
prisma.$use middleware is DEPRECATED in Prisma 5+. Prefer client extensions ($extends) for new code. Both APIs are documented here for migration.1. Creating Query Middleware
prisma.$use(async (params, next) => {
const start = Date.now();
const result = await next(params);
console.log(`${params.model}.${params.action} took ${Date.now() - start}ms`);
return result;
});
| Concept | Detail |
|---|---|
| Wraps | Every Prisma query |
| Order | Registered = outermost |
2. Understanding Middleware Params
| Field | Description |
|---|---|
model | Affected model name |
action | findUnique | create | update | delete | ... |
args | Query arguments (mutable) |
dataPath | Nested query path |
runInTransaction | Boolean flag |
3. Modifying Query Parameters
prisma.$use(async (params, next) => {
if (params.action === "findMany") {
params.args.where = { ...params.args.where, tenantId: ctx.tenantId };
}
return next(params);
});
| Use | Detail |
|---|---|
| Multi-tenancy | Inject tenant filter |
| Default sort | Inject orderBy |
4. Transforming Query Results
| Use | Detail |
|---|---|
| Redact | Mask sensitive columns |
| Decrypt | Decode at-rest encrypted fields |
| Type coerce | Convert Decimal → number |
5. Implementing Soft Delete Middleware
prisma.$use(async (params, next) => {
if (params.model === "User") {
if (params.action === "delete") {
params.action = "update";
params.args.data = { deletedAt: new Date() };
}
if (params.action === "findMany") {
params.args.where = { ...params.args.where, deletedAt: null };
}
}
return next(params);
});
| Pattern | Detail |
|---|---|
| Intercept delete | Convert to update |
| Scope reads | Filter deleted rows |
6. Adding Timestamps Automatically
| Need | Detail |
|---|---|
| Prefer schema | @default(now()) / @updatedAt |
| Custom audit cols | Add via middleware/extension |
7. Logging Query Performance
| Metric | Source |
|---|---|
| Duration | Around next() call |
| SQL | Enable log: ["query"] |
| Tracing | OpenTelemetry preview |
8. Chaining Multiple Middleware
| Order | Behavior |
|---|---|
| First registered | Outer wrapper |
| Last registered | Closest to DB call |
9. Using Async Middleware
| Aspect | Detail |
|---|---|
| Async ok | Middleware function is async |
| Avoid heavy I/O | Adds latency to every query |
10. Debugging Middleware Execution
| Tool | Use |
|---|---|
| Console logs | Inspect params/result |
| DEBUG=prisma:* | Verbose driver logging |
| Extensions | Prefer for new code (more granular hooks) |