What is Vercel’s Edge Cache and What Level of Control Do You Have

Managing caching on routes, pages, and more

March 15, 2024

By David Austin

Before we dive into examples, let cover some basics. Like, what is Edge Cache within Vercel. Any time you see reference to the Edge Cache, it’s specifically referring to Vercel’s Edge Network where effectively all your content is is stored allowing for your site and subsequent pages to load as quickly as possible.

Now, one of the challenges with cache, is it can interfere with some of the dynamic aspects of our applications. Areas like news releases or anything that’s delivering dynamic results. So understanding where it can be used and where it shouldn’t be used is very important.

Given that the Edge Network is built right in, we only need to be aware of when we want to dial down or eliminate the cache entirely. To make adjustments in these areas, we’re able to use the Cache-Control header.

Important Notes

Cache-Control

It’s very important to realize that if you’re using the Cache-Control header, it will override a matching route that may be defined in vercel.json or in the next.config.js file. Failure to remember or understand this can cause you to spend a lot of unnecessary time debugging issues that are solely due to improper caching.

For Sitecore, because there’s a good chance you’re using Next.js, it’s highly recommend to maintain all your route caching within next.config.js. This way if you were to migrate it to any host it will work properly. That said, you may choose to specify something different on a particular route.

Images And Other Static Files

Static files, i.e. any file that is served directly to the client without any server-side processing, are by default cached in the Edge Network (in Vercel) for 31 days.

If said static file doesn’t change between deployments, it can persist across deployments.

Images, will be cached on the URL and thus to invalidate said image and serve an updated image, you’ll have to add a versioning to the query string for it to be busted.

Levels Of Caching In Vercel While Using Cache-Control

Thanks to flexibility, you’re able to manage the cache control on both actual routes (i.e. URLs) as well as functions, both Serverless and Edge variety.

The default value is as follows: public, max-age=0, must-revalidate.

  • max-age can have any N number, where N is a value in seconds
  • public can also be changed to immutable - Using immutable however while powerful in that it tells a browser the content will never change, the only way to then update is to bust the cache or better yet, version said item via path name.

Cache-Control Options

While a traditional cache-control setting allows you to set the header of the response to have it cached, in Next.js you have further header customization options. And it’s these settings it’s wise to investigate and play with for each of your API routes, if you are using them. They are as follows:

  • Cache-Control
  • CDN-Cache-Control
  • Vercel-CDN-Cache-Control

It’s a good idea to manage caching at the bare minimum on all routes to avoid both impact to performance, and depending on your hosting providers tiers, potentially a cost impact as well.

Cache-Control

This header tells clients, aka, browsers, to have a TTL dependent on the set max-age. It’s also last in priority if the other two Cache Control headers are used. For example:

export async function GET() {
  return new Response('Cache-Control Header Set', {
    status: 200,
    headers: {
      'Cache-Control': 'max-age=30',
    },
  }

The above setting will inform the client / browser to have a TTL of 30 seconds.

CDN-Cache-Control

The CDN-Cache-Control will tell both Verce’s CDN and other CDNs to cache based upon the max-age set and is considered second in priority if Vercel-CDN-Cache-Control is also set.

export async function GET() {
  return new Response('Cache-Control Header Set', {
    status: 200,
    headers: {
      'CDN-Cache-Control': 'max-age=300',
    },
  }

The above setting would set the CDN Cache Control to 5 min.

Vercel-CDN-Cache-Control

The the CDN-Cache-Control, but this is specific to Vercel however this Cache Control is not returned to the browser.

For example, setting max-age=3600 for Vercel-CDN-Cache-Control will set the cache for Vercel specifically on this route to 3600 seconds.

export async function GET() {
  return new Response('Cache-Control Header Set', {
    status: 200,
    headers: {
      'Vercel-CDN-Cache-Control': 'max-age=3600',
    },
  }

Important Notes:

  • Setting Cache-Control and not setting a CDN-Cache-Control results in Vercel to remove s-maxage and state-while-revalidate headers before **sending it onto the browser.
  • You can only use the Cache-Control headers on both GET and HEAD requests. POST requests will not be cached.
  • Cache Control will not work if you have an Authorization header set nor set-cookie.

Good Practices

To give you an example of how we might use it. If we’re loading external data, we prefer to load that data via Serverless Functions. This keeps things like API keys, etc from being accessible by the browser. So from our component we’ll load that data perhaps in getStaticComponentProps or wherever, as:

const DATA_FROM_EXTERNAL = '/api/route/getData' as const;
const fetchData = async () => {
  const response = await fetch(DATA_FROM_EXTERNAL , {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      query: dataQuery,
    }),
  });
  ...
}

And then inside that API route we can perform whatever external API call we need, whether that be Edge or something else. We can then appropriately, given we’re using a GET call, cache the response appropriately to avoid “spamming” the external API.

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  try {
  ... 
    return new Response(data, {
        status: 200,
        headers: {
          'Cache-Control': 'max-age=300',
        },
      }
  }
  ...
}

So with this, we can effectively meter the API responses if we feel that the information we’re getting from the API whether its’ Edge or a 3rd party, is not changing significantly. We could also add tags if we wanted to enable revalidation of this if we wanted.



Image of Fishtank employee David Austin

David Austin

Development Team Lead | Sitecore Technology MVP x 3

David is a decorated Development Team Lead with Sitecore Technology MVP and Coveo MVP awards, as well as Sitecore CDP & Personalize Certified. He's worked in IT for 25 years; everything ranging from Developer to Business Analyst to Group Lead helping manage everything from Intranet and Internet sites to facility management and application support. David is a dedicated family man who loves to spend time with his girls. He's also an avid photographer and loves to explore new places.