Fix Cache-Control Headers on Vercel

Last updated: April 2026

Vercel sets sensible defaults but you may need to override them for API routes, static assets, or HTML pages. Set Cache-Control headers in vercel.json or next.config.js.

Audit your Vercel cache headers live โ†’

vercel.json โ€” cache headers by route pattern

{
  "headers": [
    {
      "source": "/api/(.*)",
      "headers": [
        { "key": "Cache-Control", "value": "no-store" }
      ]
    },
    {
      "source": "/_next/static/(.*)",
      "headers": [
        { "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }
      ]
    },
    {
      "source": "/(.*)\.html",
      "headers": [
        { "key": "Cache-Control", "value": "no-cache" }
      ]
    }
  ]
}

Next.js โ€” next.config.js headers

module.exports = {
  async headers() {
    return [
      {
        source: '/api/:path*',
        headers: [{ key: 'Cache-Control', value: 'no-store' }],
      },
      {
        source: '/_next/static/:path*',
        headers: [{ key: 'Cache-Control', value: 'public, max-age=31536000, immutable' }],
      },
    ];
  },
};

Next.js App Router โ€” route handler cache config

// app/api/data/route.ts
export const revalidate = 60; // ISR โ€” revalidate every 60 seconds

export async function GET() {
  const data = await fetchData();
  return Response.json(data, {
    headers: {
      'Cache-Control': 'public, max-age=60, stale-while-revalidate=300',
    },
  });
}

Vercel Edge Config โ€” stale-while-revalidate

{
  "headers": [
    {
      "source": "/api/public/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "public, max-age=60, stale-while-revalidate=300"
        }
      ]
    }
  ]
}

Verify your cache headers

curl -sI https://yourapp.vercel.app/api/data | grep -i cache-control
curl -sI https://yourapp.vercel.app/_next/static/chunks/main.js | grep -i cache-control
📚 HttpFixer Blog โ€” fix guides, explainers, and references โ†’