A route can revalidate at the right time and still use many ISR Write units when its changed output is large. Find the routes that write the most data, then reduce their HTML, React Server Component payload, or Pages Router page data.
This guide focuses on output size. If you haven't confirmed which routes, tags, or cache reasons drive the increase, start with How To Reduce ISR Revalidation Costs.
Copy link to headingUnderstand the write-unit model
Vercel durably stores ISR output in the ISR cache. ISR Reads and Writes are measured in 8 KB units. Larger changed output needs more units each time Vercel stores it.
A revalidation doesn't automatically create billed ISR Writes. When regeneration produces the same output as the previous version, Vercel doesn't incur another ISR Write. When the stored output changes, its size determines the write units. Values such as the current date, timestamps, random numbers, and generated IDs can change the rendered output on every regeneration. This can happen even when the route's source data has not changed. See Optimizing ISR Reads and Writes for common causes of unexpected writes.
Broad invalidation still matters. It can make many entries stale, which can lead to more later regenerations, ISR Reads, Function invocations, and changed outputs written as users visit those entries.
Copy link to headingBefore you start
This guide assumes you've found routes where relatively few changed regenerations produce many written bytes or write units. If you still need to distinguish between revalidation frequency, invalidation scope, and output size, start with How To Reduce ISR Revalidation Costs.
Use each affected route's current output as the baseline. Don't apply an arbitrary size threshold.
Copy link to headingRemove values that change every regeneration
A timestamp, random value, or volatile identifier can make output differ even when its source data is unchanged. Vercel's ISR usage and pricing documentation calls out new Date() and Math.random() as common causes of unexpected writes.
Check cached rendering code for new Date(), Date.now(), Math.random(), and generated UUIDs. The agent prompts below include repository searches for these patterns.
Move those values out of cached output unless they are part of the page content. For example, render a relative timestamp from stable source data instead of storing the regeneration time in the page.
Copy link to headingReduce App Router output
The App Router sends an RSC payload that includes the rendered Server Component result, references to Client Component JavaScript, and props passed from Server Components to Client Components. This payload contributes to the output generated for an ISR route. The Next.js Server and Client Components documentation explains the rendering model.
Large payloads often come from:
- Passing full content, product, or GraphQL responses into Client Components
- Placing
'use client'too high in the component tree - Rendering many Client Components in the initial view
- Storing route-specific data in a global provider
- Passing data through a provider when one small component needs it
Keep large records on the server. Pass only the fields needed for interaction.
Avoid passing the full record when the Client Component uses only a few fields:
Keep React Context providers close to the components that use them. A Context provider in the root layout can add route-specific data to every cached page. Split stable global state from page state, and keep non-interactive data in Server Components.
For a complete RSC investigation workflow, see How to Optimize RSC Payload Size. That guide covers client boundaries, component trees, large props, and local .rsc output in more detail.
Copy link to headingTrim Pages Router page data
In the Pages Router, getStaticProps returns props that Next.js serializes for the page. The browser can read them in __NEXT_DATA__. Returning a full content or GraphQL response increases cached output even when the UI uses only part of it.
Common causes include:
- Full records with internal metadata
- GraphQL responses with unused nested fields
- Product objects with inventory, variants, and recommendations that the page doesn't render
- Large arrays used only after a client interaction
- Provider values built from the complete
pagePropsobject
Select only the fields the page needs before returning props:
Query fewer fields at the source where possible. Trimming after a broad request reduces page output, but a focused database or GraphQL selection also reduces origin work and transfer.
Next.js reports a large page data warning when serialized page props exceed its warning threshold. Treat the warning as an investigation signal, then compare the affected route with its own measured baseline.
Copy link to headingReduce repeated HTML and inline assets
HTML can grow through repeated card markup, large hidden sections, inline SVGs, and other assets embedded in every page.
Check for:
- Large SVGs repeated in cards, navigation, or footers
- Full content rendered both visibly and in hidden UI
- Long lists rendered on the first response when pagination would work
- Repeated structured data or serialized state
When an SVG doesn't need direct DOM styling or animation, serve it as a static file instead of repeating its markup in every regenerated page. Next.js serves files from the public directory, which lets the browser cache the asset separately.
Don't move every SVG out of the page by default. Keep it inline when direct styling, animation, or accessibility behavior requires access to its elements. Measure the route after each change.
Copy link to headingSet up your coding agent
Before you run either prompt, install the Vercel Plugin if your coding agent supports it. The plugin gives Claude Code, Cursor, and Codex Vercel-specific skills and current product context.
Your agent still needs read access to the repository and access to the Vercel CLI.
Copy link to headingInvestigate an App Router project with an agent
Use this prompt:
Copy link to headingInvestigate a Pages Router project with an agent
Use this prompt:
Copy link to headingMeasure before and after
Use the same production route and representative source data for both measurements.
- Record the route's written bytes, write units, and revalidation volume before the change.
- Confirm frequency and invalidation scope are already appropriate.
- Remove non-deterministic values that don't belong in cached output.
- For App Router routes, compare RSC output and server-to-client props.
- For Pages Router routes, compare serialized props and
__NEXT_DATA__. - Compare HTML and repeated inline assets.
- Deploy the change and measure the same route over a comparable window.
- Check that page behavior, SEO content, and accessibility haven't changed.
- Confirm written bytes and write units decreased without increasing regeneration frequency.
If the affected routes also regenerate more often than their data changes, follow How to move from time-based to on-demand revalidation.