Response caching
VextJS provides declarative route-level response caching, configured through the cache field of the route options. When the cache is hit, parameter verification and handler execution are skipped, and the cached JSON response is returned directly.
Basic usage
Numeric abbreviation
The simplest configuration, specifying the cache validity period in milliseconds:
Complete configuration
Explicitly disable
Configuration options
RouteOptions.cache
Global configuration (config.cache)
config.cache controls the response caching runtime for the entire application. Whether a route is cached is still determined by each route's RouteOptions.cache.
The response cache runtime is handled by response-cache-kit, and the underlying cache is managed by cache-hub. Vext does not open custom Store; if you need to adjust the underlying runtime, please configure cache.cacheHub.
config.cache field
Memory cacheHub
Redis cacheHub
Redis mode is suitable for multiple instances to share response cache. When enabling Redis/MultiLevel in a business project, ioredis needs to be installed:
MultiLevel cacheHub
MultiLevel uses the memory of this process as L1 and Redis as L2. It is suitable for services that want to reduce the reading pressure of Redis but still need to share the cache across processes.
lease and distributed
lease is used to reduce multi-process cache breakdown: after the same key expires, one process obtains the lease and executes the handler, and other processes wait briefly for the cache to be written. By default, the system continues to return to the source after waiting timeout, with priority given to ensuring availability.
distributed is used to broadcast invalidation actions such as app.cache.invalidate(tag) and app.cache.clear() to other instances:
Caching behavior
By default only GET / HEAD requests are processed, and successful responses sent via res.json() are captured. res.text(), streaming responses, downloads and redirects do not write to the response cache.
Response header
Cache Key algorithm
The default key includes the request method, path, sorted query, partitionKey and vary request headers.
- Query parameters are automatically sorted (
?b=2&a=1≡?a=1&b=2) - Requests with
Authorizationare not cached by default unlesspartitionKeyis configured orallowAuthorizationCache: trueis explicitly set - When you need to differentiate cache by user or tenant, use
partitionKeyfirst - When using a custom
key,partitionKeyandvarywill still be appended to the underlying key
Scenarios without caching
204 No Contentresponse- Non-2xx status codes (3xx/4xx/5xx)
- Response contains
Set-Cookie - Response header contains
Cache-Control: no-storeorprivate - The request header contains
Cache-Control: no-storeorno-cache - With
Authorizationand nopartitionKey/allowAuthorizationCacheconfigured - Response not sent via
res.json() cache: falseexplicitly disabledcache: 0or negative valueconditionreturnsfalse- Custom
keyreturns empty string
Runtime API
Operate the cache in the route handler through app.cache:
app.cache.clear() clears the current vext response cache namespace. In Redis/MultiLevel mode, it will not perform a full Redis database clear.
Vary Headers
Different request header values will generate different cache entries:
Allow all request headers to participate in the cache key:
vary: "*" will significantly increase the number of cache entries and is generally only recommended for debugging, proxy pass-through, or interfaces that really require strong isolation.
Conditional caching
Use the condition function to control whether to use caching logic:
Custom Key
Fixed business key:
When you need to generate key according to request parameters:
Partition Key
partitionKey is the cache partition. It does not change the business response, but only isolates the underlying cache keys by user, tenant, region and other dimensions.
In the above example, even if multiple tenants access the same URL, different cache partitions will be written. Requests with Authorization will bypass the cache by default; Vext will only allow it to enter the response cache after partitionKey is configured.
If you confirm that the response is not relevant to the user, you can also enable it explicitly:
Most business interfaces recommend using partitionKey instead of directly opening allowAuthorizationCache.
Concurrently send back to the source
After the same cache key expires, if 100 requests arrive at the same time, Vext will execute the handler only once through the single-flight mechanism of response-cache-kit, and the remaining requests will wait for the same return-to-origin result to avoid cache breakdown. The request that actually executes the handler is MISS; the request that waits and reuses the same result will output HIT.
Safety precautions
Authentication routing + cache: Requests with Authorization will not be written to the response cache by default. When you need to cache authentication interfaces, use partitionKey to explicitly isolate users or tenants.
The framework detects this scenario and issues a warning on startup. Solution:
- Use
partitionKeyto isolate by user/tenant - Use
conditionto exclude requests that should not be cached - Set
allowAuthorizationCache: trueonly if the acknowledgment response is not relevant to the user