What is SWR?

🚀 SWR stands for stale-while-revalidate — A pattern you can use that keeps data fresh while also keeping the experience fast.

When to use it

🔍 An http API that is slow and changes frequently should respond with Cache-Control: max-age=1, stale-while-revalidate and the servers that serve the API should cache the responses, revalidating in the background rather than causing users to wait.

Server-side API caching

If you use Vercel, you can get started by setting Cache-Control headers in your pages/api functions.

import NotesService from 'services/notes'

export default async (req, res) => {
  const service = new NotesService()
  const notes = await service.getLatestNotes()
  res.setHeader('Cache-Control', 's-maxage=1, stale-while-revalidate, public')
  res.status(200).json({ notes })

Client side API caching

Web browsers have an HTTP cache for each user as well. Headers can be returned that browsers will respect, providing the same behavior. The difference is that the HTTP cache is personal. Client-side caching for one person doesn't make it faster for others.

To implement client side caching, see web.dev/stale-while-revalidate

Cache-Control: max-age=1, stale-while-revalidate=59

In service workers

Service workers can offer stale-while-revalidate patterns for progressive web apps. See A Workbox Example

In NextJS using static regeneration

NextJS offers incremental static regeneration. Pages will be served stale and then revalidated. Updates to the static page will happen in the background. To use it, set unstable_revalidate to the minimum time before revalidating a static page in seconds.

export async function getStaticProps({ params }) {
  const note = await new NoteService().getNote(params.slug);
  const props = { note };
  return { props, unstable_revalidate: 1 };


Caching makes things fast, and the greatest challenge is keeping data up to date. By implementing stale-while-revalidate behaviour, the cache stays fresh and the users rarely have to wait.