Skip to content

Caching

Lacis provides two caching APIs: middleware-based (createResponseCache) and handler-wrapping (withCache).

createResponseCache registers a middleware that caches responses before they are sent. Apply it globally or per-route.

import { createServer } from 'lacis'
import { createResponseCache } from 'lacis'
createServer('./routes', {
middleware: {
beforeRequest: createResponseCache({ ttl: 60 }),
},
})
OptionTypeDefaultDescription
ttlnumberrequiredCache duration in seconds
methodsstring[]['GET', 'HEAD']HTTP methods to cache
maxSizenumber500Max entries before LRU eviction
keyGenerator(req) => stringMETHOD:URLCache key function
match(req) => booleanOnly cache when this returns true
excludestring | string[]Path prefixes to skip
shouldCache(req, res) => boolean2xx status codesWhether to store a response
createResponseCache({
ttl: 60,
exclude: ['/admin', '/api/private'],
})

withCache wraps an individual handler. Useful when you want caching on one route without a global middleware.

import { withCache } from 'lacis'
import type { Request, Response } from 'lacis'
export const GET = withCache(
{ ttl: 300 },
async (req: Request, res: Response) => {
const data = await fetchExpensiveData()
res.json(data)
}
)
OptionTypeDefaultDescription
ttlnumberrequiredCache duration in seconds
maxSizenumber500Max entries before LRU eviction
key(req) => stringMETHOD:URLCache key function

When maxSize is reached, the 50 least recently used entries are evicted at once. Entries also expire individually based on ttl.

Both createResponseCache and withCache accept a store option to use an external backend instead of the in-memory default.

Upstash Redis example:

import { createResponseCache } from 'lacis'
import type { CacheStore, CacheEntry } from 'lacis'
import { Redis } from '@upstash/redis'
const redis = new Redis({ url: process.env.UPSTASH_URL!, token: process.env.UPSTASH_TOKEN! })
const store: CacheStore = {
async get(key) {
return await redis.get<CacheEntry>(key) ?? undefined
},
async set(key, entry) {
const ttl = Math.ceil((entry.expiresAt - Date.now()) / 1000)
await redis.set(key, entry, { ex: ttl })
},
}
createResponseCache({ ttl: 60, store })
// or: withCache({ ttl: 60, store }, handler)