Skip to main content

Import

import { cache } from 'hono/cache'

Usage

app.get(
  '*',
  cache({
    cacheName: 'my-app',
    cacheControl: 'max-age=3600',
  })
)

Options

The cache middleware accepts an options object:
cacheName
string | ((c: Context) => string | Promise<string>)
required
The name of the cache. Can be used to store multiple caches with different identifiers. Can be a static string or a function that returns the cache name dynamically.
wait
boolean
default:false
Whether Hono should wait for the Promise of the cache.put function to resolve before continuing with the request. Required to be true for the Deno environment.
cacheControl
string
A string of directives for the Cache-Control header. Will be appended to existing directives.
vary
string | string[]
Sets the Vary header in the response. If the original response already contains a Vary header, the values are merged, removing duplicates.
keyGenerator
(c: Context) => string | Promise<string>
Generates keys for every request in the cacheName store. Useful for caching data based on request parameters or context parameters. Defaults to using the request URL.
cacheableStatusCodes
number[]
An array of status codes that can be cached. Only responses with these status codes will be stored in the cache.

Signature

cache(options: {
  cacheName: string | ((c: Context) => Promise<string> | string)
  wait?: boolean
  cacheControl?: string
  vary?: string | string[]
  keyGenerator?: (c: Context) => Promise<string> | string
  cacheableStatusCodes?: StatusCode[]
}): MiddlewareHandler

Examples

Basic caching

app.get('*', cache({
  cacheName: 'my-app',
  cacheControl: 'max-age=3600',
}))

Custom cache key based on query params

app.get('/api/posts', cache({
  cacheName: 'posts-cache',
  keyGenerator: (c) => {
    const url = new URL(c.req.url)
    return url.pathname + url.search
  },
  cacheControl: 'max-age=600',
}))

Dynamic cache name

app.get('/api/:version/*', cache({
  cacheName: (c) => {
    const version = c.req.param('version')
    return `api-cache-${version}`
  },
  cacheControl: 'max-age=3600',
}))

Vary header for conditional caching

app.get('/api/content', cache({
  cacheName: 'content-cache',
  vary: ['Accept-Language', 'Accept-Encoding'],
  cacheControl: 'max-age=3600',
}))

Cache multiple status codes

app.get('*', cache({
  cacheName: 'my-app',
  cacheableStatusCodes: [200, 301, 404],
  cacheControl: 'max-age=3600',
}))

For Deno (with wait)

app.get('*', cache({
  cacheName: 'my-app',
  wait: true,
  cacheControl: 'max-age=3600',
}))

Behavior

  • Returns cached response immediately if available
  • Only caches responses with status codes in cacheableStatusCodes (default: 200)
  • Skips caching if response has:
    • Vary: * header
    • Cache-Control with private, no-store, or no-cache
    • Set-Cookie header
  • Appends specified Cache-Control directives without duplicating existing ones
  • Merges Vary headers and removes duplicates
  • Uses Cache API (caches.open()) which must be available in the runtime
  • If Cache API is not available, middleware becomes a no-op

Build docs developers (and LLMs) love