---
title: How to reduce ISR revalidation costs
description: Reduce ISR costs by analyzing Incremental Static Regeneration (ISR) behavior to find pages and tags that revalidate too often
url: /kb/guide/how-to-reduce-isr-revalidation-costs
canonical_url: "https://vercel.com/kb/guide/how-to-reduce-isr-revalidation-costs"
last_updated: 2026-07-17
authors: Mark Knichel, Jonas Herrmannsdörfer
related:
  - /docs/incremental-static-regeneration
  - /docs/incremental-static-regeneration/limits-and-pricing
  - /docs/caching/cache-status
  - /docs/incremental-static-regeneration/request-collapsing
  - /kb/guide/how-to-move-to-on-demand-revalidation
  - /kb/guide/update-mega-nav-min-reval
  - /kb/guide/how-to-reduce-isr-writes
  - /kb/guide/how-to-optimize-rsc-payload-size
  - /docs/caching/cdn-cache/purge
  - /docs/headers/response-headers
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

Incremental Static Regeneration (ISR) serves a cached page instantly and regenerates it in the background, so users get a fast response while your content stays current. This guide shows you how to use Vercel's ISR Observability and Logs to find routes and cache tags that revalidate more than their data changes, then decide whether to reduce frequency, narrow invalidation scope, or shrink changed output.

This guide assumes you already use ISR. For setup and framework configuration, see [Incremental Static Regeneration](https://vercel.com/docs/incremental-static-regeneration).

## Overview

In this guide, you'll learn how to:

- Understand what contributes to ISR Reads, ISR Writes, and Function invocations.
  
- Analyze revalidation volume with Vercel's ISR Observability.
  
- Use cache reasons to confirm why a route regenerated.
  
- Choose the right optimization based on frequency, scope, and output size.
  

## How ISR serves and refreshes a page

Every ISR request is served from one of three places:

- **CDN Cache:** The cache in Vercel regions that serves cached content close to the user. CDN cache reads and writes are free.
  
- **ISR Cache:** Durable storage in one Function region. Data remains cached for the duration you specify, until you invalidate it, or until it goes unaccessed for 31 days.
  
- **Origin:** Your application code runs to render a missing or stale response. The result can then be stored in the ISR Cache and distributed through CDN caches.
  

Vercel documents this two-level cache in [ISR usage and pricing](https://vercel.com/docs/incremental-static-regeneration/limits-and-pricing#isr-cache-region).

A revalidation makes affected content stale or removes it, depending on the API and profile you use. A later request can then run application code to regenerate that content. This can lead to Function invocations. Revalidation also clears affected content from regional CDN caches, which can cause later ISR Reads as those caches refill.

### Cache states in the `x-vercel-cache` header

Every ISR response carries a state in the `x-vercel-cache` header, and Logs surface the same value. See [Cache Status](https://vercel.com/docs/caching/cache-status) for the full list of states and cache reason values.

## What contributes to ISR costs

[ISR Reads and Writes use 8 KB units](https://vercel.com/docs/incremental-static-regeneration/limits-and-pricing#written-data):

- **ISR Reads:** Data read from durable ISR storage after the CDN Cache doesn't have the response.
  
- **ISR Writes:** New or changed output stored in durable ISR storage.
  
- **Function invocations:** Application code that runs for cache misses or regeneration.
  

An invalidation doesn't automatically incur an ISR Write. If regeneration produces the same output, Vercel doesn't incur another ISR Write. If the output changes, its size determines the write units. Values such as the current date, timestamps, random numbers, and generated IDs can make otherwise unchanged output different on every regeneration. See [Optimizing ISR Reads and Writes](https://vercel.com/docs/incremental-static-regeneration/limits-and-pricing#optimizing-isr-reads-and-writes) for common causes of unexpected writes.

A broad invalidation can affect many entries. This increases the potential number of later regenerations, ISR Reads, Function invocations, and changed outputs written as users visit those entries.

### Request collapsing

When many requests reach the same uncached path at once, Vercel collapses them into a single Function invocation per region. The first request runs your function. The others wait for that result instead of each triggering another invocation.

This protects the origin from a cache stampede. It also applies when Vercel serves `STALE` responses, so concurrent background revalidations collapse into one invocation. See [request collapsing](https://vercel.com/docs/incremental-static-regeneration/request-collapsing) for details.

Vercel labels collapsed requests in the cache reason field. This lets you distinguish a request that waited on a collapsed leader from one that ran its own invocation.

## Compare time-based and on-demand revalidation

ISR gives you two ways to decide when cached output becomes stale:

- **Time-based revalidation:** A fixed interval marks content stale whether or not its data changed.
  
- **On-demand revalidation:** Your application marks affected content stale after a source change.
  

Time-based revalidation fits data sources that don't expose a reliable change event. On-demand revalidation fits data such as content, products, inventory, or database records where your application can observe the change.

If event-driven data revalidates more often than it changes, follow [How to move from time-based to on-demand revalidation](https://vercel.com/kb/guide/how-to-move-to-on-demand-revalidation). It covers current Next.js APIs, paths and tags, external events, internal mutations, locales, references, and bulk changes.

## Analyze revalidation volume

Before changing code, use Observability to find where revalidation happens and whether it matches the source data's change rate.

### Find inefficient revalidation with Observability

Open the project dashboard, then go to **Observability** and select the **ISR** tab: [ISR Observability](https://vercel.com/d?to=%2F%5Bteam%5D%2F%5Bproject%5D%2Fobservability%2Fisr&title=ISR+Observability).

Use the table to find:

- Routes with high revalidation volume
  
- Paths with low utilization
  
- Tags invalidated more often than their data changes
  
- Tags attached to many ISR entries
  
- Routes with high written bytes or write units relative to their revalidation count
  

### Analyze time-based revalidation volume

Sort routes by time-based revalidations. Treat the highest-volume routes as the first investigation targets.

Compare each route's timer with how often its source data changes. A low-utilization page with a short interval can regenerate repeatedly without serving enough requests to justify it.

### Inspect revalidation by tag

Use the tag drill-down and look for:

- **High frequency:** A tag receives more invalidations than its underlying data receives meaningful changes.
  
- **Large blast radius:** One tag covers many ISR entries, so one invalidation can make many entries stale.
  

Narrow a broad tag until it describes the smallest group that shares the changed data.

### Drill into a route

Select a route to inspect its paths and tags. This isolates the exact entries that drive the route's revalidation volume.

Compare revalidation count with utilization and written bytes. High volume suggests a frequency or scope issue. Relatively few changed regenerations with many written bytes suggests an output-size issue.

### Find the reason in Logs

Logs show why a request was a `MISS`, `STALE`, `BYPASS`, or `REVALIDATED` through the cache reason field. Common reasons include:

- `**cold**` **(**`**MISS**`**):** Content wasn't in the cache, so the request went to the origin.
  
- `**collapsed**` **(**`**MISS**`**):** The request waited on a collapsed leader.
  
- `**error**` **(**`**MISS**`**):** Cache lookup failed and the request fell back to the origin.
  
- `**time-based revalidation**` **(**`**STALE**`**):** The interval elapsed. On a low-utilization route, lengthen the interval or move to on-demand revalidation.
  
- `**tag-based invalidation**` **(**`**STALE**`**):** `revalidateTag` or `revalidatePath` made the entry stale. Check the event frequency and blast radius.
  
- `**revalidation error**` **(**`**STALE**`**):** Vercel served stale output because background regeneration failed.
  
- `**draft mode**`**,** `**prerender bypass**`**, or** `**crawler**` **(**`**BYPASS**`**):** The response intentionally bypassed the ISR cache and can run a Function invocation.
  
- `**tag-based deletion**` **(**`**REVALIDATED**`**):** A purge or delete removed the entry. Check whether stale-while-revalidate behavior would avoid a blocking regeneration.
  

See [Cache Status](https://vercel.com/docs/caching/cache-status) for the current list. The investigation prompt below includes the equivalent Vercel CLI workflow for an agent.

## Choose the first optimization

Use routes, tags, cache reasons, utilization, and written bytes to choose one branch:

### Reduce excessive revalidation frequency

For data without change events, choose the longest interval that meets its freshness requirement.

For event-driven data, [move from time-based to on-demand revalidation](https://vercel.com/kb/guide/how-to-move-to-on-demand-revalidation). The focused guide explains how to choose between paths and tags, map source changes, handle external events and internal mutations, and avoid broad invalidation.

### Narrow broad invalidation

If one invalidation affects many entries, narrow it to the smallest safe path or tag. The [on-demand revalidation guide](https://vercel.com/kb/guide/how-to-move-to-on-demand-revalidation) covers scope design, locale-aware tags, shared data, and the difference between page and layout invalidation.

Shared navigation needs a separate pattern when one change would otherwise affect every page. See [Updating large-scale site navigation with minimal revalidation](https://vercel.com/kb/guide/update-mega-nav-min-reval).

### Shrink changed output

If relatively few changed regenerations produce many written bytes or write units, output size is the likely problem.

Follow [How to reduce ISR Writes by shrinking cached output](https://vercel.com/kb/guide/how-to-reduce-isr-writes). The focused guide covers App Router RSC output, Pages Router page data, repeated HTML, inline assets, and non-deterministic values. It links to [How to Optimize RSC Payload Size](https://vercel.com/kb/guide/how-to-optimize-rsc-payload-size) for the complete RSC workflow.

## Investigate with an agent

Use this prompt with a coding agent that can read your repository and use the Vercel CLI. Install the [cdn-caching](https://www.skills.sh/vercel/vercel-plugin/cdn-caching) agent skill and use this prompt:

``Investigate why ISR cost increased for this Vercel project. Start read-only. Use the Vercel CLI and the codebase. First confirm the current team and linked project. Run `vercel metrics schema` before querying metrics so you use the ISR metrics and dimensions available to this project. Use `vercel metrics` to find routes, paths, deployments, and cache tags with high revalidation volume, written bytes, or write units. Use `vercel metrics vercel.request.count --group-by cache_reason --since 24h` to compare cache reasons. Use `vercel logs --request-id <request-id> --expand --json` for representative requests. Add `--project` and `--scope` when the repository is not linked to the right project and team. Correlate the increase with deployments, source-data changes, external change events, bulk updates, traffic, and revalidation errors. Compare utilization, revalidation volume, written bytes, write units, and cache reasons. Inspect revalidate intervals, revalidatePath, revalidateTag, updateTag, cacheTag, cacheLife, event handlers, and broad layout or global-tag invalidation. Classify each likely driver as excessive frequency, broad invalidation scope, or large changed output. Return the commands used, evidence, affected routes and tags, and recommended next steps ranked by likely impact. Do not edit files.``

## Checklist

1. Attribute the increase to a project, route, and time window.
   
2. Compare it with deployments, source-data changes, bulk updates, and traffic.
   
3. Compare revalidation volume with utilization and written bytes.
   
4. Inspect frequently invalidated tags and their blast radius.
   
5. Use cache reasons to confirm why sample requests regenerated.
   
6. Route frequency or scope problems to the [on-demand revalidation guide](https://vercel.com/kb/guide/how-to-move-to-on-demand-revalidation).
   
7. Route output-size problems to the [cached-output guide](https://vercel.com/kb/guide/how-to-reduce-isr-writes).
   
8. Recheck Observability and usage after release.
   

## Next steps

- [Incremental Static Regeneration](/docs/incremental-static-regeneration) — framework setup and configuration.
  
- [ISR usage and pricing](/docs/incremental-static-regeneration/limits-and-pricing) — how reads, writes, and invocations are billed.
  
- [Purging Vercel CDN cache](/docs/caching/cdn-cache/purge) — invalidate vs. delete, and the programmatic surfaces for cache control.
  
- [Cache Status and Reasons](https://vercel.com/docs/caching/cache-status) — the full list of x-vercel-cache states and the Cache Reason shown for each.
  
- [Response headers](/docs/headers/response-headers#x-vercel-cache) — the full list of `x-vercel-cache` states and cache status values.
  
- [Request collapsing](/docs/incremental-static-regeneration/request-collapsing) — how Vercel coalesces concurrent requests to the same uncached path.