KV Cache Handler
TheKVCacheHandler provides persistent ISR caching on Cloudflare Workers using KV as the storage backend. It supports time-based expiry (stale-while-revalidate) and tag-based invalidation.
Installation
The KV cache handler is included with vinext:Quick Start
1. Create KV Namespace
Create a KV namespace via the Cloudflare dashboard or CLI:2. Configure wrangler.jsonc
Add the KV namespace to your worker config:3. Set Cache Handler in Worker
4. Use ISR in Your Pages
API Reference
Constructor
Parameters
kvNamespace (required)Type:
KVNamespaceCloudflare KV namespace binding.
optionsType:
{ appPrefix?: string }Optional configuration.
options.appPrefixType:
stringPrefix for all cache keys. Useful for multi-tenant or multi-app deployments sharing one KV namespace.
myapp:cache:key.
Methods
get
null on miss or invalidation.
Returns:
cacheState: 'stale'- Entry expired but still returned (stale-while-revalidate)cacheState: 'fresh'orundefined- Entry is fresh
set
revalidateTag
resetRequestCache
Cache Behavior
Stale-While-Revalidate
When a cache entry expires (revalidate time passes):
- The stale entry is returned immediately (
cacheState: 'stale') - Background revalidation is triggered
- Next request receives the fresh entry
Tag-Based Invalidation
Entries can be tagged for grouped invalidation:TTL Management
KV entries have two expiry concepts:- Revalidate time - When entry becomes “stale” (but still served)
- KV TTL - When entry is physically deleted from KV
revalidate: 60→ KV TTL: 600 seconds (10 minutes)revalidate: 3600→ KV TTL: 36000 seconds (10 hours)revalidate: 86400→ KV TTL: 864000 seconds (10 days)
Entry Structure
Cache entries are stored as JSON:value- The cached data (page HTML, RSC payload, fetch response, etc.)tags- Array of cache tags for invalidationlastModified- Timestamp when entry was createdrevalidateAt- Absolute timestamp (ms) when entry becomes stale
Key Prefixes
The handler uses two key prefixes:cache:- Cache entries (cache:key)__tag:- Tag invalidation timestamps (__tag:posts)
appPrefix, keys become {appPrefix}:cache:key and {appPrefix}:__tag:posts.
Tag Validation
Cache tags are validated for safety:- Max length: 256 characters
- Allowed: alphanumeric,
-,_,. - Disallowed: control characters, path separators (
/,\), colons (:)
Supported Cache Types
The KV cache handler supports all Next.js cache entry types:FETCH-fetch()responsesAPP_PAGE- App Router page renders (RSC payload + HTML)PAGES- Pages Router page rendersAPP_ROUTE- Route handler responsesREDIRECT- Redirect metadataIMAGE- Optimized images
ArrayBuffer Serialization
Some cache types containArrayBuffer fields (RSC payloads, route handler bodies, images). These are automatically:
- Converted to base64 before storage
- Restored to
ArrayBufferon retrieval
Multi-Tenant Deployments
UseappPrefix to isolate cache entries per app:
app1.example.com and app2.example.com have isolated caches in the same KV namespace.
Performance Considerations
KV Consistency
KV is eventually consistent. After aset() or revalidateTag(), it may take a few seconds for the change to propagate globally.
For strong consistency requirements, use Durable Objects instead of KV.
Tag Lookup Parallelization
Tag checks are parallelized for low latency:KV Limits
- Read latency: ~10-50ms globally
- Write latency: ~100ms-1s (eventual consistency)
- Key size limit: 512 bytes
- Value size limit: 25 MB
- Operations per day: Unlimited on paid plan, 100k/day on free plan
Example: Full Worker Setup
Related
- Route Segment Config - Configure ISR per route
- revalidateTag/revalidatePath - Manual cache invalidation
- Image Optimization - Cloudflare Images integration
- Cloudflare Bindings - Access KV, D1, R2, and other bindings