@fastify/caching

ETag, Last-Modified, Server Cache

@fastify/caching

Add HTTP cache hints to your responses and an optional server-side cache helper. Real performance gains come from combining this with a CDN or reverse proxy.

4 min read Level 2/5 #fastify#caching#performance
What you'll learn
  • Install @fastify/caching
  • Use reply.etag and expiresIn
  • Combine with a reverse-proxy or CDN cache

@fastify/caching does two things: it sets cache-related response headers and exposes a small in-process cache. Most of the real performance wins come from getting the headers right and letting a CDN do the heavy lifting.

Install & Register

npm install @fastify/caching
import caching from '@fastify/caching'

await app.register(caching, {
  privacy: 'public',
  expiresIn: 60,
})

That sets Cache-Control: public, max-age=60 on every response unless you override it.

Per-Route Headers

For hot, cacheable endpoints, set explicit headers and an ETag.

import { createHash } from 'node:crypto'

app.get('/articles/:slug', async (req, reply) => {
  const article = await app.db.articles.findUnique({ where: { slug: 'x' } })
  const etag = createHash('sha1').update(JSON.stringify(article)).digest('hex')

  reply
    .header('Cache-Control', 'public, max-age=300, stale-while-revalidate=60')
    .header('ETag', etag)
    .send(article)
})

If the request includes If-None-Match matching the ETag, return 304 to skip the body.

CDN First

The plugin gives you the headers, but the speed comes from the CDN. Front Fastify with Cloudflare, Fastly, or a Varnish layer, and the same response can serve thousands of clients for a single origin hit. Combine stale-while-revalidate with a short max-age for invisible refreshes.

Streaming Responses →