Open-Source Wikis

/

Prisma

/

Packages

/

Runtime

prisma/prisma

Runtime

Active contributors: jacek-prisma, Oleksii Orlenko, Søren Bramer Schmidt

Purpose

packages/client/src/runtime is the code that generated Prisma Clients import. When a user runs prisma generate, the generator emits a thin per-project wrapper that delegates almost everything here. This page covers ClientEngine (the request orchestrator), the two executors, and the request/response pipeline.

ClientEngine

packages/client/src/runtime/core/engines/client/ClientEngine.ts is the centerpiece of Prisma 7. It owns the lifecycle of a client-side query engine:

  • Loading the Wasm query compiler from @prisma/query-compiler-wasm
  • Compiling JSON-protocol requests into query plans
  • Dispatching plans to a LocalExecutor or RemoteExecutor
  • Translating engine-level errors into user-facing Prisma errors (PrismaClientKnownRequestError, PrismaClientUnknownRequestError, PrismaClientInitializationError)

ClientEngine is what getPrismaClient.ts instantiates inside the constructed PrismaClient. There used to be a different engine (a child process that owned a Rust binary); that engine is gone in Prisma 7.

CLIENT_ENGINE_ERROR (a constant inside ClientEngine.ts) raises a PrismaClientInitializationError with code P2038 when no driver adapter is configured. This is the single Prisma 7-only error code: the old engine could fall back to a default connection, the new one cannot.

Executors

Two implementations of Executor live next to ClientEngine:

graph LR
    Engine[ClientEngine.request] --> Plan[Compiled query plan]
    Plan --> LE[LocalExecutor]
    Plan --> RE[RemoteExecutor]

    LE --> Interp[QueryInterpreter<br/>client-engine-runtime]
    Interp --> Adapter[Driver adapter]
    Adapter --> DB[(Database)]

    RE --> HTTP[HTTPS to Accelerate]
    HTTP --> Cloud[(Prisma Accelerate)]
    Cloud --> DB

LocalExecutor

Used when the user supplies a SqlDriverAdapterFactory via the adapter constructor option. Hands the compiled query plan to QueryInterpreter from @prisma/client-engine-runtime, which executes it against the adapter's SqlQueryable. This is the path almost all users take.

RemoteExecutor

Used when accelerateUrl is configured. Serializes the query plan and POSTs it to Accelerate, which runs it server-side against a connection pool (using the same QueryInterpreter code, in fact, deployed as query-plan-executor — see that package page).

The shared contract is ExecutePlanParams in packages/client/src/runtime/core/engines/client/Executor.ts. Either executor receives:

  • The query plan
  • Transaction context (interactive transaction ID, isolation level)
  • Tracing context (OTel span linkage)
  • Comments to attach to outgoing SQL (SQL Commenter plugins)

Request lifecycle

The full lifecycle from prisma.user.findMany({ ... }) to a returned array of typed objects:

sequenceDiagram
    participant User as User code
    participant CP as compositeProxy
    participant Apply as applyModel/applyFluent
    participant RH as RequestHandler
    participant DL as DataLoader
    participant Engine as ClientEngine
    participant Exec as LocalExecutor

    User->>CP: prisma.user.findMany({...})
    CP->>Apply: invoke action
    Apply->>RH: handleRequest(action, args, dataPath)
    Note over RH,DL: DataLoader batches concurrent loads
    RH->>DL: enqueue(request)
    DL->>Engine: request(jsonProtocol)
    Engine->>Exec: execute(plan)
    Exec-->>Engine: rows
    Engine-->>DL: response
    DL-->>RH: response
    RH-->>Apply: shaped object
    Apply-->>CP: typed result
    CP-->>User: User[]

RequestHandler.ts is the seam where user-facing actions become engine requests. It applies dataPath (the chain of select/include segments accumulated during the fluent walk) to extract the user-visible shape from the engine's response, and renders any errors using core/errorRendering/.

DataLoader.ts is a per-PrismaClient batcher: relation loads issued in the same microtask tick get coalesced into one engine request when possible. This is what makes include-heavy queries efficient.

Fluent API and dataPath

prisma.user.findFirst({...}).posts() is implemented by packages/client/src/runtime/core/model/applyFluent.ts. Each .posts() call appends ['select', <relationName>] to dataPath. At unpack time in RequestHandler.ts, the runtime walks dataPath to extract the relation result.

There's a subtle correctness caveat here, called out in AGENTS.md:

Runtime unpacking in packages/client/src/runtime/RequestHandler.ts currently strips 'select'/'include' segments before deepGet. In extension context resolution, dataPath should be interpreted as selector/field pairs (select|include, relation field). Do not strip by raw string value or relation fields literally named select/include get dropped.

If you touch dataPath handling, keep this invariant in mind.

Transactions

Two flavors live under core/transaction/:

  • Batch transactionsprisma.$transaction([...]). Sequential or parallel queries with rollback on any failure.
  • Interactive transactionsprisma.$transaction(async tx => { ... }). The user holds a transaction handle and can issue queries inside the callback.

Interactive transaction IDs are owned by TransactionManager in client-engine-runtime. Savepoint behavior is provider-specific and dispatched through the adapter's Transaction (createSavepoint/rollbackToSavepoint/releaseSavepoint) rather than synthesized in TypeScript. See client-engine-runtime for details.

Error rendering

packages/client/src/runtime/core/errorRendering/ formats validation and runtime errors. The big test file applyValidationError.test.ts (3,620 lines) is the most reliable source of truth for what the rendering pipeline produces. Use it as fixture inspiration if you change rendering output.

Tracing

packages/client/src/runtime/core/tracing/ integrates with @opentelemetry/api. The companion package @prisma/instrumentation provides the auto-instrumentation entry that wraps PrismaClient operations.

Edge runtime

packages/client/edge.js exports a slimmed-down runtime suitable for edge environments (Cloudflare Workers, Vercel Edge). The web-platform checks live in packages/client-engine-runtime/src/web-platform.ts. Edge users must use a driver adapter — there is no Node-only fallback.

Entry points for modification

  • Add a new constructor option: see the five-step list in the parent page
  • Change query unpacking: RequestHandler.ts and applyFluent.ts together
  • Change error mapping: core/engines/client/ClientEngine.ts and core/errorRendering/ (plus, for driver-side errors, client-engine-runtime/src/user-facing-error.ts)
  • Add a new action: search for usages in core/model/ and add the dispatch in applyModel/applyFluent

See also

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Runtime – Prisma wiki | Factory