Drizzle caching is opt-in by default
Drizzle sends every query straight to the database by default with no hidden caching or automatic invalidation. You must explicitly opt in to use caching. The default caching strategy is 'explicit' (global: false), so nothing is cached unless you ask.
Upstash cache integration with Drizzle
Drizzle provides an upstashCache() helper for out-of-the-box Upstash Redis integration. Basic usage: import { upstashCache } from 'drizzle-orm/cache/upstash'; import { drizzle } from 'drizzle-orm/mysql2'; const db = drizzle(process.env.DB_URL!, { cache: upstashCache({ token: process.env.UPSTASH_TOKEN, url: process.env.UPSTASH_URL }) });
Upstash cache configuration options
The CacheConfig type for Upstash has these options: ex (expiration in seconds as positive integer, optional), hexOptions (set TTL on hash key fields with values 'NX', 'nx', 'XX', 'xx', 'GT', 'gt', 'LT', 'lt', optional).
Enable global caching in Upstash
Pass global: true to upstashCache() to enable caching for all queries by default. Without this setting, caching is 'explicit' mode and requires .$withCache() on individual queries.
.$withCache() method for explicit cache control
In explicit caching mode (global: false), call .$withCache() on a query to read from cache. The method accepts options: config (rewrite config for this query), tag (custom cache key instead of hashing query+params), and autoInvalidate (boolean to turn off auto-invalidation, defaults to true).
Disable cache for specific queries with global caching
When global: true is set, call .$withCache(false) on a query to disable caching for that specific query.
Cache invalidation with db.$cache.invalidate()
Use db.$cache.invalidate() to manually invalidate cache entries. Pass { tables: users } or { tables: [users, posts] } to invalidate all queries using those tables. Pass { tables: 'usersTable' } or { tables: ['usersTable', 'postsTable'] } to invalidate by table name string. Pass { tags: 'custom_key' } or { tags: ['custom_key', 'custom_key1'] } to invalidate custom tags defined in select queries.
autoInvalidate: false for eventual consistency
Setting autoInvalidate: false in .$withCache() turns off automatic cache invalidation on mutations, allowing stale data until TTL expires. Use this when data doesn't change often and slight staleness is acceptable (e.g. product listings, blog posts) or when handling invalidation manually. By default autoInvalidate is enabled.
Custom cache implementation in Drizzle
Extend the Cache class to implement custom caching. Override strategy() to return 'explicit' or 'all'. Override get(key) to retrieve cached values. Override put(key, response, tables, isTag, config) to store cache entries with table tracking for invalidation. Override onMutate(params) where params has 'tags' and 'tables' to handle cache invalidation on insert, update, or delete operations.
Custom cache config options
CacheConfig for custom cache implementations includes: ex (expiration in seconds, optional), px (expiration in milliseconds, optional), exat (Unix time in seconds when key expires, optional), pxat (Unix time in milliseconds when key expires, optional), keepTtl (retain existing TTL when updating a key, optional), hexOptions (options for HEXPIRE with values 'NX', 'XX', 'GT', 'LT', 'nx', 'xx', 'gt', 'lt', optional).
Cache limitation: raw queries not cached
Cache extension does not handle raw queries such as db.execute(sql`select 1`).
Cache limitation: transactions not cached
Using cache in transactions is not supported. Cache does not work with db.transaction() operations.
Cache temporary limitation: relational queries
Using cache with Drizzle Relational Queries (e.g., db.query.users.findMany()) is a temporary limitation that will be supported in the future.
Cache temporary limitation: views
Using cache with Drizzle views is a temporary limitation that will be supported in the future.
Transactions interact with caching layer
Transactions do not work with the Drizzle caching layer. Attempting to use cache within a transaction will not be handled by the cache extension.