Start with a freshness promise, not a cache setting
“Fresh” means different things for a pricing page, a blog article, an inventory count, and an account balance. Before selecting a revalidation interval, write down the oldest acceptable content for each route and what event should make it change. This turns caching from a framework default into a product decision.
Mostly stable
Marketing and evergreen content can tolerate a time window of minutes or hours.
Event-driven
A CMS publish, price edit, or catalog change should refresh the affected route quickly.
Per-request
Personal, authorized, or rapidly changing data should be fetched for that request.
Static generation is valuable because it removes repeated rendering work from the request path. It becomes risky only when a page has no declared route back to correctness. Give every cached route an owner, a maximum age, and a trigger that can refresh it.
Choose time-based, on-demand, or request-time rendering
Time-based revalidation is a dependable baseline for content that changes regularly but does not require immediate publication. In the Pages Router, revalidate gives Next.js permission to regenerate after the interval; visitors continue receiving a cached response while a new one is prepared.
export async function getStaticProps() {
const article = await cms.getArticle("cache-guide");
return {
props: { article },
revalidate: 300, // Content may be up to five minutes old.
};
}Use on-demand revalidation when an upstream event is the real source of truth. A publish action can refresh an article immediately instead of waiting for an arbitrary clock. Use request-time rendering when the response is user-specific, security-sensitive, or the system cannot safely serve a short-lived snapshot. The goal is not to maximize static pages; it is to meet the route's promise at the lowest practical cost.
Make on-demand revalidation a protected, idempotent operation
A revalidation endpoint is an operational control plane. Do not expose it as a public convenience URL. Authenticate the sender with a secret or signed webhook, validate the event type and payload, map the content record to known paths, and log a non-sensitive request identifier. Keep the action narrow: a changed article should not invalidate an entire site.
export default async function handler(req, res) {
if (req.query.secret !== process.env.REVALIDATION_SECRET) {
return res.status(401).json({ message: "Invalid token" });
}
const slug = req.body?.slug;
if (!slug || !/^[a-z0-9-]+$/.test(slug)) {
return res.status(400).json({ message: "Invalid slug" });
}
await res.revalidate("/blog/" + slug);
await res.revalidate("/blog");
return res.json({ revalidated: true });
}Real providers retry webhooks, so the handler must be safe to receive more than once. Validate that a requested path belongs to your site rather than accepting arbitrary paths. Store secrets only on the server and follow the environment separation practices in our Next.js secret-management guide.
Plan for stale content and failed refreshes
A cache refresh can fail because the CMS is slow, a deployment is rolling out, an upstream API has changed, or a route throws. The safe default is to preserve the last known good response, surface the failure to operators, and retry through the event source or a controlled job. Do not replace a good page with an error merely because a background refresh failed.
- Set timeouts for CMS and data dependencies so regeneration cannot hang indefinitely.
- Validate content before publishing it into a cached response.
- Alert on sustained revalidation failures and compare them with publish events.
- Keep a manual, audited recovery path for urgent corrections.
- Test the failure path in staging, including webhook retries and missing content.
When an invalidation needs to coordinate with a database change, emit it only after the transaction commits. For queued follow-up work, use the idempotency and retry patterns from our Node.js background-jobs guide.
Measure whether users see the right content at the right speed
Track publication time, webhook receipt time, revalidation result, and the first observed fresh response. This gives you an end-to-end freshness lag rather than a vague belief that a cache is working. Pair it with cache-hit behavior, route errors, Core Web Vitals, and content-related support reports. If a route is stale too often, investigate its event mapping and deployment path before shrinking every interval.
Release revalidation logic behind a controlled rollout when it changes many routes or content types. The targeting and cleanup principles in our Next.js feature-flags guide are useful safeguards for that rollout.
Next.js cache revalidation checklist
✓ Every cached route has a documented maximum age
✓ Time-based intervals match real content expectations
✓ Webhooks authenticate and validate their payloads
✓ Invalidation targets only known, affected routes
✓ Repeated events are safe and observable
✓ Failed refreshes retain the last known good page
✓ Freshness lag and failures have dashboards and alerts
✓ Staging tests cover publish, retry, and rollback paths
Ship fast pages that remain trustworthy
Endurance Softwares helps teams build fast, resilient Next.js applications with practical caching, content workflows, and production observability.