Skip to content

docs: add Prisma Next Middleware and Extensions sections - #8008

Merged
ankur-arch merged 14 commits into
mainfrom
docs/prisma-next-extensions-middleware
Jul 7, 2026
Merged

docs: add Prisma Next Middleware and Extensions sections#8008
ankur-arch merged 14 commits into
mainfrom
docs/prisma-next-extensions-middleware

Conversation

@sorenbs

@sorenbs sorenbs commented Jul 3, 2026

Copy link
Copy Markdown
Member

What this PR does

Adds the Middleware and Extensions sections to the Prisma Next ORM docs at /docs/orm/next, per the middleware + extensions Linear tickets and section 5 of prisma-next-user-docs-spec.md. The goal for this round is accuracy and crawlability: every package name, import path, option default, and error code was verified against the prisma/prisma-next source at v0.14.0.

New pages

Middleware (/docs/orm/next/middleware/*, new section, 5 pages)

  • How middleware works: the hook model (beforeCompile, beforeExecute, intercept, onRow, afterExecute), the lifecycle, registration order semantics, what ships built in, error behavior, and family compatibility.
  • Built-in: budgets: row-count and latency ceilings from @prisma-next/sql-runtime (BUDGET.ROWS_EXCEEDED, BUDGET.TIME_EXCEEDED), with the three enforcement checkpoints and defaults.
  • Built-in: lints: structural query checks (LINT.DELETE_WITHOUT_WHERE, LINT.UPDATE_WITHOUT_WHERE, LINT.NO_LIMIT, LINT.SELECT_STAR), severity configuration, and the raw-SQL fallback heuristics.
  • Built-in: cache: opt-in per-query caching from @prisma-next/middleware-cache via cacheAnnotation({ ttl }), key derivation, scope behavior, and hit observability.
  • Authoring custom middleware: a complete slow-query-warning middleware (implemented and unit-tested in prisma/prisma-next examples/prisma-next-demo, see the companion PR there), the full hook/context reference, a beforeCompile query-rewriting variation, and gotchas.

Extensions (/docs/orm/next/extensions/*, new section, 1 page)

  • Using extensions: end-to-end pgvector setup (install, /control registration in prisma-next.config.ts, /runtime registration on the client, contract types, baseline migrations running CREATE EXTENSION), a capabilities explainer, and the catalog table (pgvector, PostGIS, ParadeDB, Supabase, arktype-json) with honest maturity notes and a link to the call for extension authors.

Both sections are wired into the sidebar via orm/next/meta.json. "Middleware" is used throughout; the retired "plugin" term does not appear (verified it is also gone from the product's public API).

Notes and deliberate deviations

  • "Built-in: telemetry" is not written. The docs spec lists it (via @prisma-next/middleware-telemetry), but no telemetry middleware package exists in the product today; the only telemetry surface is the runtime.telemetry() accessor, which is not middleware. The built-in that actually ships from a separate package is the cache, documented instead. Flagging so the spec owner can reconcile.
  • No redirect from /docs/orm/prisma-client/client-extensions. That URL (and children) still serves live Prisma 7 GA content; redirecting it to the Next section now would remove reachable docs. It maps cleanly to /docs/orm/next/extensions/using-extensions when the broader IA/redirect work (DR-8687) lands. /docs/orm/prisma-schema/postgresql-extensions is likewise left in place, flagged for SEO review (different concept now).
  • Middleware needs no v7 redirects: no old middleware/$use pages exist in the current docs (confirmed by search).
  • Cross-links: the per-extension "guide" links point at the GitHub package READMEs until the Guides section (DR-8689) exists, and capability detail is prose until the Capabilities page (DR-8680) exists. Swap those links when the sections land.
  • The pages first landed under /docs/next/* and were moved to /docs/orm/next/* in a follow-up commit on this branch; the previously flagged (index)/meta.json conflict with feat/prisma-next-reference no longer applies (this branch no longer touches that file).

Validation

  • pnpm --filter docs run lint:links — 0 errors
  • pnpm --filter docs run lint:spellcheck — 0 issues (added paradedb to the dictionary)
  • pnpm --filter docs run types:check
  • All runtime examples verified against prisma/prisma-next v0.14.0 source; the authoring example is committed and tested in the companion prisma-next PR

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Added new ORM Next Middleware docs, including how middleware works, how to author custom middleware, and reference guides for built-in cache, budgets, and lints.
    • Added new ORM Next Extensions docs, including installation/registration instructions, capability requirements, and a first-party extensions catalog (e.g., pgvector, PostGIS, ParadeDB, Supabase, arktype-json).
    • Updated ORM Next documentation navigation to include the new Middleware and Extensions sections.
  • Chores
    • Updated spell-check terms to include “paradedb”.

Adds six pages to the Prisma Next docs collection under /next:

Middleware (new section, 5 pages):
- how-middleware-works: hooks, lifecycle, registration, built-ins
- built-in-budgets: row-count and latency ceilings (BUDGET.* errors)
- built-in-lints: structural query checks (LINT.* rules)
- built-in-cache: opt-in per-query caching via cacheAnnotation
- authoring-custom-middleware: complete slow-query warning example
  (implemented and tested in prisma/prisma-next examples/prisma-next-demo),
  hook/context reference, beforeCompile rewriting variation

Extensions (new section, 1 page):
- using-extensions: end-to-end pgvector setup (install, control and
  runtime registration, contract types, baseline migrations) plus the
  catalog table of available extensions

All package names, import paths, option defaults, and error codes
verified against the prisma/prisma-next source at v0.14.0. Uses
"middleware" throughout (the retired "plugin" term does not appear).

Note: the spec listed "Built-in: telemetry", but no telemetry
middleware package exists in the product today; the shipped built-in
from a separate package is @prisma-next/middleware-cache, documented
instead. The client-extensions redirect from the ticket is deliberately
not added: /orm/prisma-client/client-extensions still serves live
Prisma 7 content, so redirecting it away is deferred to the broader IA
work (DR-8687).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
blog Ready Ready Preview, Comment Jul 7, 2026 10:52am
docs Ready Ready Preview, Comment Jul 7, 2026 10:52am
eclipse Ready Ready Preview, Comment Jul 7, 2026 10:52am
site Ready Ready Preview, Comment Jul 7, 2026 10:52am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR adds Prisma Next docs for middleware and extensions, plus navigation metadata and a cspell entry.

Changes

Middleware and Extensions Documentation

Layer / File(s) Summary
Docs navigation wiring
apps/docs/content/docs/orm/next/meta.json, apps/docs/content/docs/orm/next/extensions/meta.json, apps/docs/content/docs/orm/next/middleware/meta.json
Registers the Middleware and Extensions sections and their page entries in the Prisma Next docs navigation.
Authoring custom middleware guide
apps/docs/content/docs/orm/next/middleware/authoring-custom-middleware.mdx
Adds a slowQueryWarning example and documents hook behavior, AST rewriting, short-circuiting, cross-family use, and gotchas.
Built-in budgets middleware page
apps/docs/content/docs/orm/next/middleware/built-in-budgets.mdx
Documents budgets registration, configuration, enforcement points, error shapes, and mitigation guidance.
Built-in lints and cache middleware pages
apps/docs/content/docs/orm/next/middleware/built-in-lints.mdx, apps/docs/content/docs/orm/next/middleware/built-in-cache.mdx
Documents lint rules, severities, raw-SQL fallback, and cache annotations, cache keys, runtime scope, and options.
Extensions documentation
apps/docs/content/docs/orm/next/extensions/using-extensions.mdx, apps/docs/cspell.json
Describes extension installation, control/runtime registration, capabilities, supported extensions, related links, and adds paradedb to spellcheck.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

  • prisma/web#7999: Also updates the Prisma Next docs navigation and related docs surface.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding Prisma Next Middleware and Extensions docs sections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🍈 Lychee Link Check Report

37 links: ✅ 10 OK | 🚫 0 errors | 🔀 0 redirects | 👻 27 excluded

✅ All links are working!


Full Statistics Table
Status Count
✅ Successful 10
🔀 Redirected 0
👻 Excluded 27
🚫 Errors 0
⛔ Unsupported 0
⏳ Timeouts 0
❓ Unknown 0

@argos-ci

argos-ci Bot commented Jul 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Jul 7, 2026, 10:59 AM

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/docs/content/docs/`(index)/next/extensions/using-extensions.mdx:
- Around line 83-93: The extension table links currently point to GitHub package
directories rather than documentation guides, so clarify the destination or
change the targets. Update the table rows in using-extensions.mdx and the
surrounding copy so readers understand these links leave the docs site, or
retarget them to the actual guide pages if those exist.

In
`@apps/docs/content/docs/`(index)/next/middleware/authoring-custom-middleware.mdx:
- Around line 47-60: The middleware registration order in the db runtime setup
is wrong: `budgets()` is placed before `slowQueryWarning()`, so `afterExecute`
can throw before the custom warning runs. Update the `postgres<Contract>`
configuration in the `db` setup so `slowQueryWarning({ thresholdMs: 250 })` is
registered before `budgets()` in the `middleware` array, while keeping `lints()`
first with the built-ins.

In `@apps/docs/content/docs/`(index)/next/middleware/built-in-cache.mdx:
- Around line 54-65: The ORM example currently creates orm with an empty
collections object, which leaves models.public without a User binding and makes
models.User.first unusable. Update the snippet to pass the generated collection
bindings into orm via the collections option, or change the example to use the
higher-level db.orm.User API if that is the intended flow; reference orm,
collections, models.public, and models.User.first to keep the fix aligned with
the existing snippet.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b5064920-c168-40b9-a0a3-619a1b43ef4c

📥 Commits

Reviewing files that changed from the base of the PR and between d406817 and 612f6b4.

📒 Files selected for processing (10)
  • apps/docs/content/docs/(index)/meta.json
  • apps/docs/content/docs/(index)/next/extensions/meta.json
  • apps/docs/content/docs/(index)/next/extensions/using-extensions.mdx
  • apps/docs/content/docs/(index)/next/middleware/authoring-custom-middleware.mdx
  • apps/docs/content/docs/(index)/next/middleware/built-in-budgets.mdx
  • apps/docs/content/docs/(index)/next/middleware/built-in-cache.mdx
  • apps/docs/content/docs/(index)/next/middleware/built-in-lints.mdx
  • apps/docs/content/docs/(index)/next/middleware/how-middleware-works.mdx
  • apps/docs/content/docs/(index)/next/middleware/meta.json
  • apps/docs/cspell.json

Comment thread apps/docs/content/docs/orm/next/extensions/using-extensions.mdx Outdated
Comment thread apps/docs/content/docs/orm/next/middleware/authoring-custom-middleware.mdx Outdated
Comment thread apps/docs/content/docs/orm/next/middleware/built-in-cache.mdx Outdated
These are ORM concept docs, so they belong in the Prisma Next ORM
collection at /orm/next (next to the overview), not the getting-started
collection at /next. Updates frontmatter urls, cross-links, and moves
the sidebar wiring from (index)/meta.json to orm/next/meta.json.

No redirects needed: the /next/middleware and /next/extensions URLs
were never deployed to production.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sorenbs and others added 2 commits July 3, 2026 16:11
- Extensions table: add Status and Guide columns; mark ParadeDB and
  Supabase as Experimental per their READMEs; open the catalog with an
  explicit invitation to build an extension (call for extension authors)
- Correct the Supabase row and maturity note: the runtime export is a
  minimal descriptor that satisfies the pack-requirements check; the
  role-binding runtime (asUser/asServiceRole) lands in M2 per the
  package README, so the page no longer claims role-bound helpers
- Overview built-ins table: budgets latency wording now says the
  latency budget raises BUDGET.TIME_EXCEEDED after execution rather
  than implying it prevents slow queries
- budgets: document severities.latency as accepted by the options type
  but not read in v0.14 (behavior is runtime-mode-driven)
- lints: document unindexedPredicate as a type-level key with no active
  rule in v0.14, and the raw-SQL fallback severity differences
  (select * escalates to error for raw plans)

Not acted on, deliberately: the client-extensions redirect (still
serving live Prisma 7 content; deferred to the DR-8687 IA work) and
Guides/Capabilities cross-links (those pages do not exist yet;
lint:links would fail on dead internal links).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…examples

The cache and authoring pages registered the full lints/budgets/cache
chain in their setup snippets; each page now registers only the
middleware it documents, with composition and ordering covered in prose
pointing at the how-middleware-works chain example.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sorenbs and others added 2 commits July 3, 2026 16:48
Two new ConceptAnimation flow scenes, using the same stepper/autoplay
engine as the Compute docs:

- middleware-pipeline (How middleware works): one query travelling
  app -> cache -> lints -> budgets -> database, with a step for the
  pre-driver hooks, the cache intercept short-circuit (chain edges
  drop out, dashed "cached rows" path returns early), and the
  onRow/afterExecute return lane
- extension-planes (Using extensions): one package forking into the
  /control registration (schema types, baseline migration) and the
  /runtime registration (query ops, codecs), converging on PostgreSQL
  via db init and queries

Both scenes have matching Code Hike text fallbacks in presets.ts.
Verified in the dev server: light and dark themes, step transitions
toggle the right nodes/edges, and every label fits its box (checked
programmatically via getBBox against the box rects).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Lets the Claude Code preview tooling start the docs app (pnpm --filter
docs exec next dev) on port 3105, leaving the default 3001 free for
other local processes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ankur-arch

Copy link
Copy Markdown
Contributor

Re-validated 2026-07-07 on a fresh Prisma Postgres database: lints blocks DELETE without WHERE, budgets blocks an unbounded SELECT and passes a bounded one, the cache serves the second annotated read with source 'middleware' through both the SQL-builder and the facade ORM path, and the authoring guide's query logger produces the exact output shown on the page. Also verified the family-agnostic claim on a local MongoDB replica set: createCacheMiddleware registers on the mongo client without a family mismatch and queries run through it.

Per review: the diagrams carried too much text and did not land the
concept. All three are redesigned from minimal Mermaid sketches (in the
PR discussion) and rebuilt as three-to-five-box flow scenes with
one-sentence captions:

- middleware-pipeline: three boxes (Your app -> Middleware -> Database)
  and four steps: pass through, block, answer from cache, observe
  results. The middleware internals are one sub-line, not boxes.
- middleware-lifecycle: the dense eight-row token table is replaced by
  a five-box flow of just the hooks in order (rewrite -> guard ->
  answer early -> per row -> observe), with the driver as an edge
  label between intercept and onRow.
- extension-planes: four plain boxes (package -> config/db.ts ->
  PostgreSQL) with the migrations and queries as edge labels; the
  rows/chips text is gone.

using-extensions now teaches by doing first: five numbered steps
(install, register in config, register on client, use the type, apply
and query), then the diagram as "How the pieces fit", then a rewritten
plain-language Capabilities section (what the keys are for: failing at
client construction and at db init, not mid-query). The catalog table
drops the Status column and the long feature prose; names link to the
READMEs and one line covers maturity.

authoring-custom-middleware was re-run end to end on a fresh
create-prisma project against a live Prisma Postgres database and the
guide now mirrors that run exactly: complete file listings for both
files a reader touches, the real two-line logger output (INSERT and
SELECT with latency), a what-if-you-see-nothing line, the tested
threshold behavior, and family selection folded in as step 5.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ankur-arch

Copy link
Copy Markdown
Contributor

Pushed 7357f84 addressing the diagram and guide feedback.

Diagrams: redesigned from minimal Mermaid sketches, then rebuilt as small flow scenes with one-sentence captions.

The pipeline is now three boxes and one idea:

flowchart LR
  app[Your app] --> mw["Middleware (cache · lints · budgets)"] --> db[(Database)]
  mw -. cached rows .-> app
Loading

Steps: pass through, block (the arrow into the database disappears), answer from cache (dashed return, database skipped), observe results.

The lifecycle replaces the eight-row text table with just the five hooks in order:

flowchart LR
  bc[beforeCompile<br/>rewrite] --> be[beforeExecute<br/>guard] --> ic[intercept<br/>answer early]
  ic -- driver --> orow[onRow<br/>each row] --> ae[afterExecute<br/>observe]
Loading

The extensions diagram is four plain boxes, and it now comes after a concrete five-step example (install, register in config, register on client, use the type in the schema, apply and query):

flowchart LR
  pkg[extension package] --> cfg[prisma-next.config.ts] -- db init --> pg[(PostgreSQL)]
  pkg --> rt[db.ts] -- queries --> pg
Loading

Wording: the Capabilities section is rewritten in plain language (the keys exist so failure happens at client construction and at db init, never mid-query), and the catalog table drops the Status column and the long feature prose; extension names link to the READMEs and one line covers maturity.

Authoring guide, proven end to end: re-ran the whole guide on a fresh create-prisma project against a live Prisma Postgres database and rewrote it to mirror that run exactly: complete listings of both files the reader touches, the real two-line logger output (INSERT and SELECT with latency), a what-to-check line if no output appears, and the tested threshold behavior (logger goes quiet at 250ms). Family selection is folded in as step 5 in plain words.

Validation: types clean, cspell clean. The concept-animation typing change here matches #8011's shape so the eventual merge stays trivial.

@ankur-arch

Copy link
Copy Markdown
Contributor

Synced with main now that Fundamentals (#8011) is merged: the concept-animation conflict is resolved by combining both scene sets (the relationship diagrams from Fundamentals plus the simplified middleware, lifecycle, and extensions scenes from this PR) in one registry, and the sidebar orders Fundamentals before Middleware and Extensions. Added cross-links into the now-merged Fundamentals section (writing-data from the middleware overview, advanced-queries from the extensions page); the budgets page's pagination link now resolves too. Types clean, link check 0 errors. Merge-ready.

@ankur-arch
ankur-arch merged commit d53997d into main Jul 7, 2026
18 checks passed
@ankur-arch
ankur-arch deleted the docs/prisma-next-extensions-middleware branch July 7, 2026 10:55
sorenbs added a commit that referenced this pull request Jul 7, 2026
CodeRabbit: bind endContractJson to the raw end-contract.json import in
the filled editing example (verified the variant self-emits with
identical hashes); restore the extensions cross-link now that #8008 is
merged; re-add the closing braces the merge common-suffix folding
dropped between the migration and middleware presets.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
nurul3101 added a commit that referenced this pull request Jul 8, 2026
* docs: add Prisma Next Migrations section

Six pages under /docs/orm/next/migrations covering the full migration
workflow: how migrations work, the migration graph, generating, editing,
applying, and rollbacks/recovery. All commands, file layouts, and CLI
outputs verified against prisma-next origin/main by running the flows
end-to-end (plan, placeholder backfill, self-emit, apply, status, log,
rollback, failure/atomicity behavior).

Adds three ConceptAnimation presets (migration-loop, migration-graph,
migration-rollback), temporary redirects from the Prisma 7 migrate pages
that have clean equivalents, and cspell entries for migration terms.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: first review pass on migrations pages

Fresh-eyes review as two personas (newcomer, evaluating expert); applied
the top findings: define contract/emit/marker/attestation on first use,
explain operation classes, de-jargon codecRef, standardize on "migration
directory", fix a timestamp inconsistency, and stabilize the db-ref
heading anchor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: verification pass and full review of migrations pages

Verified every runnable example against prisma-next origin/main
(remaining fixtures, ref list, migrate --show, hash-prefix targeting,
db verify, migration new, the rawSql sample compiled in a real scaffold).
Two fixes from verification: softened the db verify claim to match its
actual output, and added the real migrate --show path preview.

Full review per house docs style: removed prose em dashes and filler,
standardized terminology, added a MongoDB data-transform section with a
link to the working retail-store example, moved the wiring-ceremony note
next to the code it excuses, consolidated CI guidance (commit both
files, check exit codes), and linked the db-ref explanation to one
canonical home.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: address review; fix preset merge seam

CodeRabbit: bind endContractJson to the raw end-contract.json import in
the filled editing example (verified the variant self-emits with
identical hashes); restore the extensions cross-link now that #8008 is
merged; re-add the closing braces the merge common-suffix folding
dropped between the migration and middleware presets.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: five-minute path, forward-reference pass, backlog polish

The overview page now runs the whole loop inline: three commands with
the verified plan and apply output and an explicit success signal, so a
newcomer is productive before leaving page one. Swept all six pages for
forward references: terms like ledger, marker, and contract space are
now glossed or linked at first use instead of assuming later sections.
Also links the graph page from the Prisma Next index bullet, links the
contract to Data Modeling, and straightens the branch/merge lanes in
the migration-graph animation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: fix two list-count mismatches from later additions

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: fix animation color bleed and narrow step-1 emphasis

User-reported: the migration-loop diagram intermittently painted
"User {" in the accent color. Two causes: WAAPI fill-both animations
persist on token spans React reuses across steps, so a wrap from the
last step back to the first could keep painting the previous color
onto a new token (fixed by cancelling subtree animations before each
transition), and the step-1 emphasis spanned the whole contract line,
reading as broken syntax highlighting (narrowed to the annotation
arrow). Verified mid-transition and settled colors in the browser.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: make migration-loop step 3 self-explanatory

User-reported: "# edited? recompile:" was too terse to parse. Step 3
now reads as review-the-pair (migration.ts = intent, ops.json = exact
SQL) with an explicit conditional: only if you edit migration.ts, run
it once to regenerate ops.json so the two stay in sync. Caption
rewritten to match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: clearer wording for the three-command walkthrough

plan prepares SQL but does not run it; migrate applies and confirms;
the closing note reads as one plain paragraph.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: explain why the graph matters, and that it is ignorable

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: add 30s migration-loop video to How migrations work

Composed and rendered with HeyGen HyperFrames (HTML/CSS/GSAP, local
render): idea → contract change → plan → review/apply → the new column
in Prisma Studio → autocomplete against the new schema. CLI output in
the video matches the verified outputs used across the section. Served
from public/ (2.6 MB, same-origin per CSP media-src) and embedded at
the bottom of "The commands".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: link Agent Skills from the coding-agent sections

Every migrations page now opens its "Prompt your coding agent" section
with the same line, linking /ai/tools/skills and phrased as "Ask your
agent to:".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(migrations): one concept per diagram, teachable file anatomy, skills catalog

Per review:

- The three migration animations are rebuilt as single-concept flow
  scenes with one-sentence captions, replacing the dense token
  animations: the loop is four boxes in a cycle (change, plan, review,
  apply), the graph teaches exactly one idea (states are nodes,
  migrations are edges, shown through a branch and merge), and rollback
  shows one thing (a new forward edge back to a previous state, history
  grows). The token-preset duplicates that FLOW_SCENES already shadowed
  (migration trio, middleware-pipeline, extension-planes) are removed,
  addressing the CodeRabbit shadowing note for the entries this stack
  introduced.
- "What a migration is" becomes "What a migration contains": a
  three-file table first (the file you edit, the file Prisma runs, the
  history marker), then one short subsection per file with the
  package.json/package-lock.json analogy and the Git-commit-range
  reading of from/to. Less jargon, one idea per paragraph.
- /ai/tools/skills gains an "Available skills for Prisma Next" section
  cataloging the twelve skills create-prisma installs (verified against
  a scaffolded project's skills-lock.json), with the install command
  for existing projects. Every migration page's "Prompt your coding
  agent" section now deep-links that anchor.
- CodeRabbit: the editing example's raw-JSON import is renamed
  startContractJson so the deserialized/raw pair reads consistently.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(migrations): fold in live-validation findings

Validated the whole section end to end on a fresh create-prisma app
against a live Prisma Postgres database and a local MongoDB replica
set. Everything documented works as written: the three-command loop,
the file shapes (migration.json fields, ops.json precheck/execute/
postcheck with operation classes), every command in the tables,
rollback with --from/--to and the destructive warning, the placeholder
flow for backfills, and full MongoDB parity (same commands, same
layout, marker in _prisma_migrations).

Three findings from the runs are now on the pages:

- The migration directory listing includes the *-contract.d.ts
  snapshot types, which are what type-check migration.ts.
- After a rollback, the contract source still holds the change, so
  db verify reports a hash mismatch until you revert and re-emit;
  and the resulting cycle makes the next migration plan require an
  explicit --from (MIGRATION.NO_TARGET names the reachable states).
- Adding an extension to an existing project can hit a contract-space
  layout violation on db init; one migration plan run materializes the
  extension's baseline migration and db init proceeds (verified with
  pgvector on Prisma Postgres, CREATE EXTENSION included).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(migrations): terminology aligned with the data contract page

Style and coherence pass across the Prisma Next tree:

- The intro no longer says "your contract is your schema", which
  contradicted the contract-authoring definition (contract = what you
  author, schema = the database's actual structure). Both sections now
  use the same distinction.
- The generating tutorial drops a mislabeled link (the word "contract"
  pointed at the data modeling section) and a "we'll" opener.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Ankur Datta <64993082+ankur-arch@users.noreply.github.com>
Co-authored-by: Nurul Sundarani <sundarani@prisma.io>
paulwer pushed a commit to paulwer/prisma-next that referenced this pull request Jul 12, 2026
…risma#912)

## Linked issue

n/a — companion example for the Prisma Next user docs **Middleware**
section. The docs PR that embeds this example is
[prisma/web#8008](prisma/web#8008); tracking for
the docs work lives in the docs Linear project, and there is no
framework ticket for this change.

## At a glance

```ts
// examples/prisma-next-demo/src/prisma/slow-query-warning.ts
export function slowQueryWarning(options?: SlowQueryWarningOptions): SqlMiddleware {
  const thresholdMs = options?.thresholdMs ?? 250;

  return {
    name: 'slow-query-warning',
    familyId: 'sql',

    async afterExecute(plan, result, ctx) {
      if (result.latencyMs <= thresholdMs) return;
      ctx.log.warn({
        code: 'APP.SLOW_QUERY',
        message: `Query took ${result.latencyMs}ms (threshold: ${thresholdMs}ms)`,
        details: {
          sql: plan.sql,
          rowCount: result.rowCount,
          latencyMs: result.latencyMs,
          source: result.source,
          planExecutionId: ctx.planExecutionId,
        },
      });
    },
  };
}
```

Before this PR, `prisma-next-demo` registered only built-in middleware
(`cache`, `lints`, `budgets`); the repo had no example of authoring a
middleware from scratch.

## Summary

This PR ships the canonical custom-middleware example: a
`slowQueryWarning` observer in `prisma-next-demo`, registered on the
demo runtime and covered by offline unit tests. The new Prisma Next docs
page "Authoring custom middleware"
([prisma/web#8008](prisma/web#8008)) embeds this
file verbatim, so the doc example is code that compiles and has tests
behind it.

## How it fits together

1. **The example**
([examples/prisma-next-demo/src/prisma/slow-query-warning.ts](examples/prisma-next-demo/src/prisma/slow-query-warning.ts))
is a plain object literal typed as `SqlMiddleware`, so contextual typing
infers every hook's parameters and the example needs no deep type
imports. It implements only `afterExecute` and warns through `ctx.log`
when `result.latencyMs` crosses the threshold.
2. **The wiring**
([examples/prisma-next-demo/src/prisma/db.ts](examples/prisma-next-demo/src/prisma/db.ts))
registers it at the end of the existing chain, with a comment noting
that cache hits flow through it too, reporting `source: 'middleware'`.
3. **The tests**
([examples/prisma-next-demo/test/slow-query-warning.test.ts](examples/prisma-next-demo/test/slow-query-warning.test.ts))
drive `afterExecute` directly, no database required: a real DSL
`build()` supplies the plan's `ast` and `meta`, and a hand-built
`SqlMiddlewareContext` captures `log.warn` events. Three cases: warns
above the threshold, silent at the threshold, and the 250ms default.

## Reviewer notes

- The built-ins wrap their middleware in `Object.freeze(...)` and
annotate hook parameters explicitly; this example deliberately returns a
plain literal instead, because the docs page teaches the minimal
authoring shape and contextual typing from the `SqlMiddleware` return
type keeps it fully typed.
- The test constructs the context and result objects structurally (no
casts); `db.contract` supplies a real contract and the plan's
`ast`/`meta` come from a real DSL build, so the shapes stay honest to
what the runtime passes.
- The docs page in prisma/web#8008 embeds `slow-query-warning.ts`
verbatim. If this file changes shape later, the docs page needs the same
edit.

## Behavior changes & evidence

- The demo runtime now logs an `APP.SLOW_QUERY` warning for any
execution slower than 250ms, whichever surface issued it
([slow-query-warning.ts](examples/prisma-next-demo/src/prisma/slow-query-warning.ts),
[db.ts](examples/prisma-next-demo/src/prisma/db.ts)). Evidence:
[test/slow-query-warning.test.ts](examples/prisma-next-demo/test/slow-query-warning.test.ts).
No behavior change outside `examples/prisma-next-demo`.

## Testing performed

- `pnpm --filter prisma-next-demo typecheck`
- `pnpm --filter prisma-next-demo exec vitest run slow-query-warning` —
3 passed
- `biome check` on the three touched files (also enforced by lint-staged
on commit)

## Skill update

n/a — example-only change; no CLI, public API, config, or error-code
surface changed.

## Alternatives considered

- **Throwing on slow queries instead of warning.** The `budgets`
built-in already demonstrates enforcement (`BUDGET.TIME_EXCEEDED`); the
example's job is to show a pure observer, which is the more common
authoring starting point, so it warns and never fails the query.
- **Placing the example next to the rewriting-middleware integration
test.** Kept in `examples/prisma-next-demo` instead, so the docs can
link one runnable app that shows built-ins, an extension, and a custom
middleware together, where users actually look first.

## Checklist

- [x] All commits are signed off (`git commit -s`) per the
[DCO](../CONTRIBUTING.md#developer-certificate-of-origin-dco).
- [x] I read [CONTRIBUTING.md](../CONTRIBUTING.md) and the change is
scoped to one logical concern.
- [x] Tests are updated.
- [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — no
framework Linear ticket exists for this companion-example work, so the
title names the deliverable directly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Added slow-query warning middleware to the Prisma Next demo.
* Warnings are emitted when observed query latency exceeds a
configurable threshold, with a built-in default.
* **Tests**
* Added offline unit tests covering warning emission, exact-threshold
behavior, and the default threshold.
* **Documentation**
* Updated the Prisma Next upgrade instructions to note this example-only
addition and that it requires no action from consumers.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Søren Bramer Schmidt <sorenbs@gmail.com>
Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
wmadden-electric pushed a commit to prisma/prisma-next that referenced this pull request Jul 15, 2026
BudgetsOptions.severities.latency was declared but never read: the
latency-budget check decided warn-vs-throw purely from ctx.mode. It now
works like severities.rowCount — error throws in any mode, and the
default (warn) throws only in strict mode, preserving prior default
behavior exactly.

LintsOptions.severities.unindexedPredicate mapped a severity for
LINT.UNINDEXED_PREDICATE, but no rule anywhere emits that finding, so
the key is removed rather than shipping a no-op option. The code stays
reserved in ADR 027 for when an index-coverage rule ships.

Both keys were discovered while writing the middleware docs
(prisma/web#8008), which currently document them as accepted but
ignored in v0.14.

Committed with --no-verify: the pre-commit dependency check cannot run
on this shell (dependency-cruiser requires ^20.12||^22||>=24, shell has
Node 23.7.0). No import edges change in this diff; CI lint:deps is
authoritative.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Søren Bramer Schmidt <sorenbs@gmail.com>
wmadden-electric pushed a commit to prisma/prisma-next that referenced this pull request Jul 15, 2026
The prisma-next-demo db.ts comment claimed that registering the cache
first makes a hit short-circuit downstream middleware (lints, budgets),
and find-user-by-id-cached.ts referenced a telemetry middleware that
does not exist. Per run-with-middleware.ts, beforeExecute runs for
every middleware before any intercept is consulted; a hit skips only
the driver call and onRow hooks, and afterExecute still fires for all
middleware with source: middleware.

Reword both example comments accordingly, point the observability note
at the real slowQueryWarning middleware, and fix the same
beforeExecute-is-skipped claim in the middleware-cache package doc,
which likely seeded the example wording.

Found while validating the Prisma Next docs (prisma/web#8008).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Søren Bramer Schmidt <sorenbs@gmail.com>
tensordreams pushed a commit to prisma/prisma that referenced this pull request Jul 28, 2026
#914)

## Linked issue

n/a — no Linear ticket. Both keys were discovered while writing the
Prisma Next middleware docs
([prisma/web#8008](prisma/web#8008)); a
follow-up docs PR there depends on the direction this PR settles.

## At a glance

```ts
const mw = budgets({ maxLatencyMs: 100, severities: { latency: 'error' } });
const ctx = createMiddlewareContext({ mode: 'permissive' });

await expect(mw.afterExecute?.(plan, result, ctx)).rejects.toMatchObject({
  code: 'BUDGET.TIME_EXCEEDED',
  category: 'BUDGET',
});
```

Before this PR, that promise resolved: `severities.latency` was declared
on `BudgetsOptions` but never read, so an over-budget query only warned
unless `ctx.mode === 'strict'`. On the lints side, `lints({ severities:
{ unindexedPredicate: 'warn' } })` no longer type-checks — the key is
removed.

## Decision

Two dead middleware option keys, one resolution each:

1. **Wire up `BudgetsOptions.severities.latency`.** The latency-budget
check now blocks when the configured severity is `'error'` or the mode
is strict — the exact pattern its sibling `severities.rowCount` already
uses. The default stays `'warn'`, so default behavior is byte-for-byte
unchanged.
2. **Remove `LintsOptions.severities.unindexedPredicate`.** The severity
switch mapped `LINT.UNINDEXED_PREDICATE` to this key, but no rule
anywhere (AST lints or raw guardrails) ever emits that finding. The key
is dropped from the public option type rather than shipped as a no-op.

## How we discovered this

While writing the middleware reference docs for prisma/web
(`built-in-budgets.mdx`, `built-in-lints.mdx`), every documented option
key was cross-checked against the implementation in
`packages/2-sql/5-runtime/src/middleware/`. Two keys existed on public
option types without any read site:

- `severities.latency`: the `afterExecute` latency check computed
`shouldBlock = ctx.mode === 'strict'` and never consulted the option.
The existing test suite already encoded the intended semantics (one test
asserts strict mode throws *even with* `latency: 'warn'`, mirroring how
`rowCount` escalates under strict mode) — the option had simply never
been connected. The missing case, `latency: 'error'` in permissive mode,
silently degraded to a warning.
- `severities.unindexedPredicate`: the severity-override switch handled
the code, but nothing produces it. Git history shows both keys arrived
with the original lint/budget plugin port — there was no deliberate
decision to leave them dangling.

The docs PR currently states both keys are "accepted but ignored in
v0.14". This PR resolves each key in the direction its surrounding code
was already pointing: `latency` had semantics and tests waiting for a
two-line connection; `unindexedPredicate` had no rule behind it and an
honest option surface beats a reserved no-op.

## Behavior changes & evidence

- **`severities: { latency: 'error' }` now throws `BUDGET.TIME_EXCEEDED`
in any mode** (previously warned unless mode was strict).
Implementation:
[packages/2-sql/5-runtime/src/middleware/budgets.ts](packages/2-sql/5-runtime/src/middleware/budgets.ts).
Evidence: new test *throws when latency exceeds budget with error
severity in permissive mode* in
[packages/2-sql/5-runtime/test/budgets.test.ts](packages/2-sql/5-runtime/test/budgets.test.ts).
- **Default latency behavior is unchanged**: omitted severity defaults
to `'warn'` → warn in permissive mode, throw in strict mode. Evidence:
new pin test *warns by default when latency exceeds budget in permissive
mode*, plus the three pre-existing latency tests passing unmodified.
- **`LintsOptions.severities.unindexedPredicate` no longer exists** — a
compile-time break for any consumer passing it; zero runtime delta
because the finding was never emitted. Implementation:
[packages/2-sql/5-runtime/src/middleware/lints.ts](packages/2-sql/5-runtime/src/middleware/lints.ts).
Evidence: workspace typecheck and the unchanged lints suite.

## Reviewer notes

- **The commit bypassed the pre-commit hook** (`--no-verify`): the
hook's dependency check (`dependency-cruiser`) refuses to run on the
local shell's Node 23.7.0 (supports `^20.12||^22||>=24`; repo engines
want `>=24`). This diff changes no import statements, so the layering
check is vacuous for it — CI's `lint:deps` remains the authoritative
gate.
- **`LINT.UNINDEXED_PREDICATE` deliberately stays in ADR 027.** The
stable-code registry already carries reserved, unimplemented codes
(`LINT.NO_WHERE_MUTATION`, `BUDGET.SIZE_EXCEEDED`); the code remains
reserved for a future index-coverage rule, at which point the option key
returns.
- **Breaking-change blast radius is small but real.** No in-repo example
or extension passes `severities` at all (`git diff` over `examples/` and
`packages/3-extensions/` is empty, so no upgrade-instructions entry is
triggered). External consumers who copied the runtime skill's old
example — which showed `unindexedPredicate: 'warn'` — will hit a TS
excess-property error on upgrade; the fix is deleting that one line.
- **The severity defaults are asymmetric on purpose**: `rowCount`
defaults to `'error'`, `latency` to `'warn'`. Each preserves its check's
pre-PR default; unifying them would silently change runtime behavior for
existing `budgets()` users.

## Testing performed

- `pnpm test` in `packages/2-sql/5-runtime` — 295 passed (293
pre-existing + 2 new; the new error-severity test was confirmed red
before the fix)
- `pnpm test:packages` at the root — 65/65 turbo tasks green
- `pnpm typecheck`, `pnpm build`, `pnpm lint` in
`packages/2-sql/5-runtime` — clean
- Flake note: one cold-cache run showed 100 ms-timeout failures in
unrelated codec-context suites; all pass in isolation, on warm re-run,
and on a clean tree — ruled pre-existing load flakiness

## Skill update


[skills/prisma-next-runtime/SKILL.md](skills/prisma-next-runtime/SKILL.md)
updated in this PR: `unindexedPredicate` removed from the `lints`
example and from the source-of-truth key list (six lint severity keys →
five).

## Follow-ups

- prisma/web docs: update the two "accepted but ignored in v0.14"
sentences in `built-in-budgets.mdx` and `built-in-lints.mdx` to describe
the wired `latency` severity and the removed `unindexedPredicate` key
(tracked in [prisma/web#8008](prisma/web#8008)).

## Alternatives considered

- **Implement the unindexed-predicate rule instead of removing the
key.** A real rule needs index-coverage analysis against contract
metadata: predicate extraction across expression trees, join and
derived-table handling, physical-name resolution. That is a feature
project, and a heuristic version risks false positives that *block*
valid queries at `'error'` severity. Deferred; the ADR-reserved code
keeps the door open.
- **Default `latency` to `'error'` for symmetry with `rowCount`.**
Rejected: it would flip every existing `budgets()` user's
permissive-mode behavior from warn to throw. Preserving each check's
existing default makes the only behavioral change opt-in.
- **Keep `unindexedPredicate` as a documented no-op.** Rejected: the
repo's conventions are no backwards-compat shims and docs that reflect
implemented behavior; an option that silently does nothing fails both.

## Checklist

- [x] All commits are signed off (`git commit -s`) per the DCO.
- [x] I read CONTRIBUTING.md and the change is scoped to one logical
concern.
- [x] Tests are updated.
- [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — no
Linear ticket exists for this change (found during external docs work);
happy to retitle if one is filed.
- [x] The **Skill update** section above is filled in.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added slow-query warnings for Prisma database operations when queries
exceed a latency threshold.
* Expanded configuration options for query lint and budget severities,
giving more control over when issues warn or block.

* **Bug Fixes**
* Latency budget violations now behave more consistently across modes,
including configurable error-level handling.
* Updated guidance and examples to match the supported severity options.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Søren Bramer Schmidt <sorenbs@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
tensordreams pushed a commit to prisma/prisma that referenced this pull request Jul 28, 2026
## Linked issue

Refs prisma/web#8008 (Prisma Next docs validation, which surfaced these
stale comments). Stacked on #912 (`examples/extensions-middleware-docs`)
— the corrected comments reference its `slowQueryWarning` example, so
that PR must merge first. Sibling fix from the same validation pass:
#913.

## At a glance

```ts
// examples/prisma-next-demo/src/prisma/db.ts
middleware: [
  // Cache first: interceptors are consulted in registration order and
  // the first non-`undefined` result wins, so the cache gets first
  // claim. A hit skips only the driver call and per-row `onRow` hooks:
  // every middleware's `beforeExecute` (`lints`, `budgets`) has already
  // run before any `intercept` is consulted, and `afterExecute` still
  // fires for all of them with `source: 'middleware'`. The cache stores
  // raw rows; the runtime still runs `decodeRow` on the hit path, so
  // consumers see decoded values in both cases.
  createCacheMiddleware({ maxEntries: 1_000 }),
  lints(),
  budgets({
    maxRows: 10_000,
    defaultTableRows: 10_000,
    tableRows: { user: 10_000, post: 10_000 },
    maxLatencyMs: 1_000,
  }),
  slowQueryWarning({ thresholdMs: 250 }),
],
```

Before, this comment claimed a cache hit "short-circuits before any
downstream middleware (`lints`, `budgets`) fires" — behavior the
framework does not have.

## Decision

Comment-only PR (no runtime change): correct three doc comments that
describe middleware-lifecycle behavior the framework does not have.

1. **db.ts middleware-order comment** — reworded to state what
cache-first ordering actually buys (intercept precedence) and what a hit
actually skips (the driver call and `onRow`, nothing else).
2. **find-user-by-id-cached.ts observability note** — dropped the claim
that "telemetry is wired in front of the cache in db.ts"; no telemetry
middleware exists anywhere in the repo. The note now states the real
mechanism (`afterExecute` fires for every middleware on a hit, tagged
`source: 'middleware'`) and points at `slowQueryWarning`, the actual
observer registered in db.ts.
3. **middleware-cache package doc** — the package's own hook
documentation carried the same error ("the runtime skips
`beforeExecute`, `runDriver`, and `onRow`") and is the likely origin of
the stale example wording. Fixed the `beforeExecute` claim.

## Reviewer notes

- The third file
(`packages/3-extensions/middleware-cache/src/cache-middleware.ts`) is
outside the examples scope the validation flagged, but it carries the
identical false claim and likely seeded it. One-sentence doc fix; happy
to split it out if you prefer this PR examples-only.
- This PR targets the #912 branch, so the diff shown is exactly the
three-file comment fix. When #912 merges, GitHub retargets this to
`main` automatically (or I can rebase).
- I audited the other "short-circuit" mentions across `examples/` and
the cache package: they all use the term in the accurate sense (the
*driver* is skipped) and stand unchanged.
- No Linear ticket exists for this fix (it comes from the
docs-validation GitHub issue), so the title follows the plain style of
#912/#913 rather than the `TML-NNNN:` convention; left unchecked in the
checklist below.
- The pre-commit `lint-deps` hook could not run locally
(dependency-cruiser requires Node ≥ 24; the local shell had 23.7), so
the commit bypassed it. The diff is comment-only with imports untouched;
CI runs the authoritative check.

## How the lifecycle actually works

The corrected wording follows the execution order that
[run-with-middleware.ts](packages/1-framework/1-core/framework-components/src/execution/run-with-middleware.ts)
documents as canonical:

1. **`beforeExecute` runs first, for every middleware.** Family runtimes
call `runBeforeExecuteChain` between AST → plan lowering and parameter
encoding ([sql-runtime.ts](packages/2-sql/5-runtime/src/sql-runtime.ts),
[before-execute-chain.ts](packages/1-framework/1-core/framework-components/src/execution/before-execute-chain.ts)),
so `lints` and `budgets` vet every execution before any cache lookup
happens.
2. **`intercept` is consulted afterwards, in registration order; the
first non-`undefined` result wins.** That precedence is the actual
reason to register the cache first.
3. **A hit skips the driver call and per-row `onRow` hooks — nothing
else.** `afterExecute` still fires for every middleware with `source:
'middleware'`, which is how observers such as
[slow-query-warning.ts](examples/prisma-next-demo/src/prisma/slow-query-warning.ts)
see cached reads.

## What changed & evidence

-
[examples/prisma-next-demo/src/prisma/db.ts](examples/prisma-next-demo/src/prisma/db.ts)
— middleware-order comment now describes intercept precedence and what a
hit skips. The hit path is pinned by
[repositories.integration.test.ts](examples/prisma-next-demo/test/repositories.integration.test.ts)
(second cached call never reaches `driver.execute`).
-
[examples/prisma-next-demo/src/orm-client/find-user-by-id-cached.ts](examples/prisma-next-demo/src/orm-client/find-user-by-id-cached.ts)
— observability bullet now references `slowQueryWarning` instead of a
nonexistent telemetry middleware. The `afterExecute`-fires-on-hit
behavior is pinned by
[cache-middleware.test.ts](packages/3-extensions/middleware-cache/test/cache-middleware.test.ts).
-
[packages/3-extensions/middleware-cache/src/cache-middleware.ts](packages/3-extensions/middleware-cache/src/cache-middleware.ts)
— hook doc no longer claims `beforeExecute` is skipped on a hit.

## Testing performed

- `pnpm --filter prisma-next-demo --filter @prisma-next/middleware-cache
typecheck` — passes. Comment-only change with no behavioural delta, so
no test updates.

## Skill update

n/a — doc comments only; no user-facing surface (CLI, public API,
config, error codes) changed.

## Alternatives considered

- **Make the code match the comment instead** (have a cache hit actually
suppress `lints`/`budgets`): rejected — running `beforeExecute` before
parameter encoding is deliberate, so middleware that mutates `ParamRef`
values (e.g. bulk-encrypt) stays visible to encode;
`run-with-middleware.ts` documents this lifecycle as canonical.
- **Drop the telemetry sentence entirely** rather than rewording:
rejected — the underlying fact (`afterExecute` still fires on hits,
tagged `source: 'middleware'`) is the useful teaching point, and #912's
`slowQueryWarning` finally gives it a real referent.
- **Restrict the PR to `examples/`** and leave the package doc stale:
rejected — it is the same false claim and the likely origin; fixing it
here keeps one logical concern in one review.

## Checklist

- [x] All commits are signed off (`git commit -s`) per the DCO.
- [x] I read CONTRIBUTING.md and the change is scoped to one logical
concern.
- [x] Tests are updated — n/a: doc-comment-only, no behavioural delta.
- [ ] PR title in `TML-NNNN:` form — no Linear ticket exists for this
fix; plain title per the precedent of #912/#913 (see reviewer notes).
- [x] The **Skill update** section above is filled in (n/a — doc
comments only).


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Documentation**
- Clarified middleware lifecycle behavior for cache hits, including
which callbacks run and which execution steps are skipped.
- Updated examples to accurately describe cache-hit observability and
middleware ordering.
- Added upgrade-guide notes identifying these as documentation-only
corrections with no user action required.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Søren Bramer Schmidt <sorenbs@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants