---
title: "Query Caching"
description: "Query Caching in Drizzle ORM provides a standardized mechanism to intercept database execution paths, checking a cache layer before executing a query against the underlying driver. This architectur..."
last_updated: "2026-07-02T09:35:18.842973+00:00"
canonical_url: "https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/technical/utilities-testing/query-caching"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [drizzle-orm/src/singlestore/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/singlestore/session.ts)
- [drizzle-orm/src/bun-sql/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/bun-sql/session.ts)
- [drizzle-orm/src/postgres-js/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/postgres-js/session.ts)
- [drizzle-orm/src/gel/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/gel/session.ts)
- [drizzle-orm/src/gel-core/db.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/gel-core/db.ts)
- [drizzle-orm/src/tidb-serverless/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/tidb-serverless/session.ts)
- [drizzle-orm/src/libsql/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/libsql/session.ts)
- [drizzle-orm/src/pg-proxy/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/pg-proxy/session.ts)
- [drizzle-orm/src/d1/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/d1/session.ts)
- [drizzle-orm/src/op-sqlite/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/op-sqlite/session.ts)
- [drizzle-orm/src/mysql-proxy/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/mysql-proxy/session.ts)
- [drizzle-orm/src/xata-http/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/xata-http/session.ts)
- [drizzle-orm/src/vercel-postgres/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/vercel-postgres/session.ts)
- [drizzle-orm/src/neon-serverless/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/neon-serverless/session.ts)
- [drizzle-orm/src/sqlite-proxy/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/sqlite-proxy/session.ts)
- [drizzle-orm/src/node-postgres/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/node-postgres/session.ts)
- [drizzle-orm/src/mysql2/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/mysql2/session.ts)
- [drizzle-orm/src/planetscale-serverless/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/planetscale-serverless/session.ts)
- [drizzle-orm/src/neon-http/session.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/neon-http/session.ts)
- [drizzle-orm/src/pg-core/query-builders/select.ts](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/pg-core/query-builders/select.ts)
</details>

Query Caching in Drizzle ORM provides a standardized mechanism to intercept database execution paths, checking a cache layer before executing a query against the underlying driver. This architecture decouples the database driver from the caching strategy, allowing for consistent query result memoization across diverse targets like PostgreSQL, MySQL, and SQLite.

The system is fundamentally driven by `queryWithCache`, a method typically exposed via the `PreparedQuery` classes of individual drivers. This method acts as a control-flow interceptor: it evaluates the current query and its parameters, checks if a cache hit exists, and either returns the cached data or proceeds to the provided driver execution callback to fetch fresh results and cache them.

By utilizing this abstraction, developers ensure that expensive or frequent read operations are optimized without modifying the core query execution logic. The integration relies on a `Cache` interface, defaulting to a `NoopCache` if no provider is specified, ensuring the system remains functional even without an explicit caching backend.

## The `queryWithCache` Mechanism

The `queryWithCache` method is the core orchestrator. While the implementation varies slightly by driver, the pattern remains consistent: receive an execution task as an asynchronous callback, and wrap it with a cache lookup.

When a query is prepared, the caching configuration—including options for controlling the cache—is passed down to the prepared query instance. Upon `execute()`, the system invokes `queryWithCache`, passing the query string and parameters. The implementation effectively performs a check-then-store loop, where it first looks for the data in the provided cache instance. If the cache result is empty, the original `client.query` (or equivalent) is executed, and its result is pushed back into the cache for future requests.

```typescript
// Example pattern found across multiple implementations (e.g., node-postgres)
return this.queryWithCache(rawQuery.text, params, async () => {
    return await client.query(rawQuery, params);
});
```
Sources: [drizzle-orm/src/node-postgres/session.ts:148-150](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/node-postgres/session.ts#L148-L150)

## Caching Lifecycle and Configuration

Caching is initialized at the driver session level. Every session constructor accepts an optional `options` object containing a `cache` implementation. If a session is initiated without one, `NoopCache` is instantiated, providing a safe, no-operation interface that maintains structural compatibility without performing side effects.

| Option | Type | Default | Purpose |
| :--- | :--- | :--- | :--- |
| `cache` | `Cache` | `NoopCache` | Defines the storage backend for query results. |

Sources: [drizzle-orm/src/singlestore/session.ts:13-18](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/singlestore/session.ts#L13-L18), [drizzle-orm/src/bun-sql/session.ts:105-108](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/bun-sql/session.ts#L105-L108)

## Interaction with Prepared Queries

Prepared queries act as the container for caching configurations. When a query is executed, the resulting object is a `PreparedQuery` instance. During this instantiation, the cache configuration is injected into the constructor. 

This is where the distinction between "raw" query execution and prepared execution occurs. In the `execute` path, the `PreparedQuery` uses its held configuration to determine how to interact with the cache orchestrator. By attaching this to the prepared query instance, Drizzle preserves the necessary state to execute the cached lookup at runtime, long after the original build-time configuration has passed.

Sources: [drizzle-orm/src/singlestore/session.ts:236-248](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/singlestore/session.ts#L236-L248), [drizzle-orm/src/postgres-js/session.ts:141-152](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/postgres-js/session.ts#L141-L152)

## Integration in Driver Sessions

The driver-specific sessions are responsible for mapping the session-wide cache instance to the prepared queries they generate.

The dependency flow is:
1. `Drizzle` instance initialized with `sessionOptions` (including `Cache`).
2. `Session` receives `Cache` and passes it to `prepareQuery`.
3. `PreparedQuery` inherits the `Cache` reference.
4. `PreparedQuery.execute()` calls `this.queryWithCache(...)`.

This hierarchy ensures that all queries executed within a single session instance utilize the same cache instance, enabling session-wide optimizations.

```mermaid
graph TD
    A["db.select()"] --> B["PreparedQuery"]
    B --> C["Session.prepareQuery()"]
    C --> D["PreparedQuery instance"]
    D --> E["PreparedQuery.execute()"]
    E --> F["queryWithCache()"]
    F --> G["Cache Interface"]
```
Sources: [drizzle-orm/src/node-postgres/session.ts:233-246](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/node-postgres/session.ts#L233-L246), [drizzle-orm/src/neon-serverless/session.ts:220-233](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/neon-serverless/session.ts#L220-L233)

## Architectural Design Trade-offs

The caching system is designed for maximum compatibility across disparate drivers, leading to the following trade-offs:

| Design Choice | Benefit | Cost |
| :--- | :--- | :--- |
| **Session-level caching** | Consistent interface across all drivers | Coupling session instances to specific cache instances |
| **Callback-based `queryWithCache`** | Allows driver-specific execution logic to remain encapsulated | Requires wrapping every execution branch in a closure |
| **NoopCache default** | Zero-config usage without boilerplate | Requires extra injection to actually enable persistent storage |

Sources: [drizzle-orm/src/singlestore/session.ts:101-103](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/singlestore/session.ts#L101-L103), [drizzle-orm/src/node-postgres/session.ts:208-219](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/node-postgres/session.ts#L208-L219)

> [!TIP]
> Always check if your specific driver and database version support the prepared query format you are using, as some serverless drivers (like PlanetScale) may impose limitations on how queries are executed within transactions versus standard queries, potentially affecting the efficacy of the query cache.

## Working with `NoopCache`

The `NoopCache` class implements the `Cache` interface with empty methods. This design ensures that the session-wide reference to a `Cache` object is always defined, preventing null-pointer exceptions in the `PreparedQuery` execution logic without requiring the user to explicitly handle cases where caching is disabled.

Sources: [drizzle-orm/src/singlestore/session.ts:13-18](https://github.com/blade47/drizzle-orm/blob/main/drizzle-orm/src/singlestore/session.ts#L13-L18)

## Related

- [Query Builder Core](https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/technical/query-engine/query-builder-core)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/llms.txt) for all pages in this wiki.
