Caching
Lacis provides two caching APIs: middleware-based (createResponseCache) and handler-wrapping (withCache).
Middleware approach
Section titled “Middleware approach”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 }), },})Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
ttl | number | required | Cache duration in seconds |
methods | string[] | ['GET', 'HEAD'] | HTTP methods to cache |
maxSize | number | 500 | Max entries before LRU eviction |
keyGenerator | (req) => string | METHOD:URL | Cache key function |
match | (req) => boolean | — | Only cache when this returns true |
exclude | string | string[] | — | Path prefixes to skip |
shouldCache | (req, res) => boolean | 2xx status codes | Whether to store a response |
Excludes
Section titled “Excludes”createResponseCache({ ttl: 60, exclude: ['/admin', '/api/private'],})Handler wrapping
Section titled “Handler wrapping”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) })Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
ttl | number | required | Cache duration in seconds |
maxSize | number | 500 | Max entries before LRU eviction |
key | (req) => string | METHOD:URL | Cache key function |
LRU eviction
Section titled “LRU eviction”When maxSize is reached, the 50 least recently used entries are evicted at once. Entries also expire individually based on ttl.
Distributed store
Section titled “Distributed store”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)