---
title: Manage cache tags for external origins
description: Learn how to use cache tags to optimally serve fresh content on Vercel when content from your external origin changes
url: /kb/guide/how-to-manage-cache-tags-for-external-origins
canonical_url: "https://vercel.com/kb/guide/how-to-manage-cache-tags-for-external-origins"
published: 2026-03-24
last_updated: 2026-03-25
authors: Vercel
related:
  - /docs/routing/rewrites
  - /docs/cli
  - /docs/project-configuration/vercel-json
  - /docs/cli/routes
  - /docs/caching/cdn-cache
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

This guide shows you how content served from an external origin through Vercel’s CDN can be cached and selectively invalidated so it is only regenerated when data changes.

## Why use Vercel's CDN for external origins

Vercel's CDN improves performance and security when proxying requests to external origins, or origins that are hosted somewhere other than Vercel. The CDN reduces latency by caching content close to the user in all Vercel Regions worldwide, while the Vercel Firewall protects against threats like DDoS attacks, bot traffic, and malicious requests before they reach your servers.

## The problem

Users want to see content delivered very quickly from anywhere in the world. Caching improves performance by storing and serving the content close to users, but the content also needs to be fresh and updated as soon as data changes. When data changes, you have two options for how to make sure the content is fresh:

1. **Purge all cached content** - This option is too coarse and hurts performance and costs for unchanged content. Users have to make a request back to the origin on the next request which will be slow.
   
2. **Purge specific content** - This option requires assigning tags to specific pages that are updated at the same time. Content can be invalidated so that a stale page is served to the user on the next request while the cache is refreshed in the background.
   

Cache tags solve this by letting you organize cached responses into groups that you can invalidate at the same time. Other requests that are tagged differently are unaffected. Cache tags may also be referred to as surrogate keys on other platforms.

The rest of this guide will walk you through how to use and invalidate cache tags in your application.

## Prerequisites

- A Vercel project with [rewrites to an external origin](https://vercel.com/docs/routing/rewrites#rewrites-to-external-origins)
  
- An external origin that can set response headers
  
- The [Vercel CLI](https://vercel.com/docs/cli) installed
  

## Caching rewrites to an external origin on Vercel

A rewrite routes a request to a different destination without changing the URL in the browser. Unlike redirects, the user won't see the URL change.

To set up a rewrite, configure the `vercel.json` with the following code:

```json
{
  "rewrites": [
    {
      "source": "/api/(.*)",
      "destination": "https://api.yourdomain.com/api/$1"
    }
  ]
}
```

The flow for a request will be:

1. User requests `yourdomain.com/api/products/123`
   
2. Vercel CDN checks for cached content
   
3. If not cached, Vercel fetches from `api.yourdomain.com/api/products/123`
   
4. Your server responds with content and cache tags
   
5. Vercel caches the response with those tags
   

## Step 1: Set cache tags from your external server

Configure your server to set the `Vercel-Cache-Tag` header:

```javascript
app.get('/api/products/:id', async (req, res) => {
  const product = await getProduct(req.params.id);
  
  const tags = [
    `product-${req.params.id}`,
    `category-${product.category}`,
    'products'
  ];
  
  if (product.featured) {
    tags.push('homepage');
  }

  res.setHeader('Vercel-Cache-Tag', tags.join(','));
  res.setHeader('Cache-Control', 's-maxage=3600, max-age=60, stale-while-revalidate=86400');

  res.json(product);
});
```

**What each tag does:**

- `product-123` - Invalidate when this specific product changes
  
- `category-electronics` - Invalidate when any product in this category changes
  
- `products` - Invalidate when the product catalog changes
  

## Step 2: Install and configure Vercel CLI

```bash
npm install -g vercel
vercel login
```

If you have multiple teams, make sure that you have selected the right team:

```bash
vercel teams switch your-team-name
```

## Step 3: Invalidate cache tags

Now that the Vercel CDN is caching content, you can selectively invalidate specific cache tags to see new content being picked up. When cache tags are invalidated, the next request will return the stale content while the Vercel CDN is refreshing the cache contents in the background. This maintains performance while making sure that subsequent requests get the fresh content.

There are different ways that content can be invalidated on Vercel

### Invalidate cache tags in code

Cache tags can be invalidated directly in code if you have a function or webhook that runs when data changes.

**Option 1: Direct invalidation in your update function**

The `invalidateByTags` function can be called from server side code in the same project that the tag is defined in.

```javascript
import { Vercel } from "@vercel/sdk";

const vercel = new Vercel({
  bearerToken: "<YOUR_BEARER_TOKEN_HERE>",
});

async function updateProduct(id, data) {
  await database.products.update(id, data);
  
  const tags = [
    `product-${id}`,
    `category-${data.category}`,
    'products'
  ];

  if (data.featured) {
    tags.push('homepage');
  }
  
  await vercel.edgeCache.invalidateByTags({
    projectIdOrName: "<value>",
    teamId: "team_1a2b3c4d5e6f7g8h9i0j1k2l",
    slug: "my-team-url-slug",
    requestBody: { tags },
  });
  
  return { success: true, invalidated: tags };
}
```

**Option 2: CMS webhook handler**

If data is updated in an external CMS, you can create a webhook route handler to receive the event when data changes and choose which tags to invalidate.

```javascript
import { Vercel } from "@vercel/sdk";

const vercel = new Vercel({
  bearerToken: "<YOUR_BEARER_TOKEN_HERE>",
});

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }
  
  const { event_type, resource_id, resource_type, data } = req.body;
  
  let tags = [];
  
  if (resource_type === 'product') {
    tags = [
      `product-${resource_id}`,
      `category-${data.category}`,
      'products'
    ];
    if (data.featured) tags.push('homepage');
  } else if (resource_type === 'category') {
    tags = [`category-${resource_id}`, 'categories'];
  }
  
  if (tags.length === 0) {
    return res.status(400).json({ error: 'No tags to invalidate' });
  }
  
  try {
    await vercel.edgeCache.invalidateByTags({
      projectIdOrName: "<value>",
      teamId: "team_1a2b3c4d5e6f7g8h9i0j1k2l",
      slug: "my-team-url-slug",
      requestBody: { tags },
    });
    res.json({ success: true, invalidated: tags });
  } catch (error) {
    res.status(500).json({ error: 'Cache invalidation failed' });
  }
}
```

### Invalidate via Vercel CLI

The Vercel CLI can also be used to invalidate at any time.

```bash
# Single tag
vercel cache invalidate --tag product-123


<!-- docsgraph:related -->
## Related pages

> **For AI agents:** Follow these links to understand how this page connects to the rest of the Vercel ecosystem. For the full cross-link map (inbound, outbound, prerequisites, and semantic neighbors), see the .graph.md link below.

- [Purge CDN Cache](https://vercel.com/docs/caching/cdn-cache/purge?from=related) — Learn how to invalidate and delete cached content on Vercel's CDN, including cache keys and manual purging options.
- [vercel cache](https://vercel.com/docs/cli/cache?from=related) — Learn how to manage cache for your project using the vercel cache CLI command.
- [Data Cache](https://vercel.com/docs/caching/runtime-cache/data-cache?from=related) — Vercel Data Cache is a specialized cache that stores responses from data fetches in Next.js App Router
- [Debug Cache Issues](https://vercel.com/docs/caching/cdn-cache/debug-cache-issues?from=related) — Diagnose stale content and fix CDN cache, data cache, and build cache issues using the CLI.
- [Runtime Cache](https://vercel.com/docs/caching/runtime-cache?from=related) — Vercel Runtime Cache is a specialized cache that stores responses from data fetches in Vercel functions
- [Using Vercel as a Standalone CDN](https://vercel.com/kb/guide/using_vercel_as_a_cdn?from=related) — Use Vercel's external rewrites to proxy and cache content from external websites or APIs through Vercel's global edge ne
- [How to reduce ISR revalidation costs](https://vercel.com/kb/guide/how-to-reduce-isr-revalidation-costs?from=related) — Reduce ISR costs by analyzing Incremental Static Regeneration \(ISR\) behavior to find pages and tags that revalidate to
- [Set cache control headers for functions](https://vercel.com/kb/guide/set-cache-control-headers?from=related) — Learn how to set headers to cache your function's responses.
- [How to troubleshoot stale content returned from the Edge Network when using an external proxy or CDN](https://vercel.com/kb/guide/how-to-troubleshoot-stale-content-returned-from-the-edge-network-when-using-an-external-proxy-or-cdn?from=related) — Learn how to diagnose and fix stale content issues when using external proxies or CDNs with Vercel. Understand troublesh
- [How to Configure the Cache-Control Response Header in Vercel Projects](https://vercel.com/kb/guide/how-to-configure-the-cache-control-response-header-in-vercel-projects?from=related) — After reviewing this guide, you will be able to set a cache-control header of any value to be returned when a specific p

Full cross-link map for this page: [/kb/guide/how-to-manage-cache-tags-for-external-origins.graph.md](/kb/guide/how-to-manage-cache-tags-for-external-origins.graph.md)
<!-- /docsgraph:related -->

# Multiple tags (comma-separated)
vercel cache invalidate --tag "product-123,homepage,electronics"
```

**Purge all cache:**

Invalidate is the recommended option, but the Vercel CLI can also purge all cache content. This option isn’t recommended since it causes a blocking request to the external origin, but it can be used when all content must be updated.

```bash
# Purge all CDN cache
vercel cache purge --type cdn

# Purge all cache types
vercel cache purge
```

## Set cache tags via routing rules

If you are not able to set cache tags in the response from your external origin, you can still set cache tags on Vercel using [routing rules](https://vercel.com/docs/project-configuration/vercel-json).

**Setting cache tags in vercel.json**

```json
{
  "routes": [
    {
      "source": "/products/electronics/(.*)",
      "destination": "https://api.example.com/api/products/$1",
      "headers": {
        "Vercel-Cache-Tag": "product-$1,category-electronics"
      }
    }
  ]
}
```

**Setting cache tags from the CLI**

Routing rules to set cache tags can also be set using the CLI to add routing rules without requiring you to change any code. Use the `vercel routes` [CLI command](https://vercel.com/docs/cli/routes):

```bash
# Add cache tags for the category and product ID when rewriting the request to the external origin
vc routes add "Electronics" --src "/products/electronics/:id" --src-syntax path-to-regexp --action rewrite --dest "https://api.example.com/api/products/:id" --set-response-header 'Vercel-Cache-Tag=product-$1,category-electronics'
```

## Next steps

Cache tags can be incrementally added to your application and optimized based on usage patterns and how often data is updated. Learn more about caching in the [Vercel CDN Cache documentation](https://vercel.com/docs/caching/cdn-cache).