resp.revalidate() not propagating globally: Regional cache inconsistency in multi-region deployment

Description: We’re experiencing a critical issue with res.revalidate() in our Next.js Page Router app where revalidation isn’t propagating to all CDN regions. When we trigger revalidation, the cache clears successfully in the region where the request was handled (e.g., sfo1), but other regions (e.g., sin1 or hkg1 edge nodes) continue serving stale content—sometimes several hours old.

This leads to a “Split-Brain” scenario where users see different versions of our site depending on their geographic location. We have verified that the x-vercel-cache header remains HIT with a high age value in regions that weren’t manually revalidated, even after the API call returned { revalidated: true }.

We first noticed this on December 18th, and it is still ongoing.

Current Behavior:

  • res.revalidate() clears the cache successfully only in the local/nearest region.

  • Other global regions (especially those behind a reverse proxy in different continents) continue serving stale cached content.

  • Users in different geographic locations see inconsistent content.

  • The only reliable way to force a global refresh is a full production redeploy with “Clear Cache” enabled.

Expected Behavior:

  • When res.revalidate() is called, the invalidation signal should propagate across the entire Vercel Edge Network globally.

  • All users, regardless of their location, should see the updated content once the revalidation process completes.

Steps to Reproduce:

  1. Deploy a Page Router site to multiple regions (e.g., sfo1, iad1, sin1).

  2. Update data in the backend and trigger res.revalidate() via an API route.

  3. Verify that the region handling the API request (check x-vercel-id) now serves updated content (x-vercel-cache: MISS/REVALIDATED).

  4. Access the same URL from a different geographic region (e.g., via VPN or a regional proxy).

  5. Observe that the content remains stale and x-vercel-cache is still HIT with a high age.

Project Information:

  • Framework: Next.js 13.4.7

  • Router: Page Router

  • Environment: Production

  • Deployment Regions: iad1, sfo1, sin1

  • Architecture: Custom domain via Geolocation DNS, with a Nginx reverse proxy for specific regions.

Extra Infomation:

Here is an example from a non affected area(Domain A):

X-Vercel-Id: cle1::sfo1::brm55-1769481429897-0e2982f0e5f4

This is a response header from a user in an affected region showing stale data(Domain B).

  1. Regional Stale Content: Regardless of whether we access the site via Domain A or Domain B, as long as the x-vercel-id indicates that the request is being served by the sin1 (Singapore) region, the content remains stale.
  2. Persistent Cache in sin1: Even after a successful res.revalidate() call is triggered (usually processed by sfo1), the sin1 node continues to serve old data with a high age value, effectively ignoring the global invalidation signal.
  3. The sin1 Correlation: This confirms that the issue is not specific to our Nginx configuration (Domain B), as the direct access via Domain A also hits the same stale cache whenever the Vercel Edge Network routes the traffic through the sin1 region.

X-Vercel-Id: hkg1::sin1::g695t-1769481563414-98b996a6f0fb

Additional Technical Inquiries for Vercel Engineering:

In addition to the issue described above, we would like to clarify the following technical points regarding Vercel’s Edge architecture:

1. Global Propagation Mechanism of res.revalidate() Could you explain the internal mechanism for cache synchronization across different regions when res.revalidate() is called? Specifically, is the invalidation signal broadcasted globally to all Edge PoPs (Points of Presence) immediately, or is there a “lazy” synchronization logic that depends on the primary deployment region? We are seeing successful revalidation in the region where the API was called, but other regions seem to remain isolated with stale data.

2. Routing Logic and Region Selection (x-vercel-id Analysis) We have been monitoring the x-vercel-id header and noticed some unexpected routing behavior:

  • Stale Content via sin1: Whenever the data is fetched through the sin1 region, the content returned is consistently stale.

  • Inconsistent Routing: When accessing from Hong Kong, we observe the request being routed as hkg1 -> sfo1 or sometimes other paths. What determines this routing logic? Why isn’t the request consistently served by the nearest compute region?

  • Inactive Region (iad1): Despite having iad1 as one of our deployed regions, we have never seen it appearing in the response headers (e.g., ...::iad1::...), even when requests are initiated from nodes geographically close to that region. How does Vercel decide which regions are “active” for a given deployment?

3. Best Practices for Nginx Reverse Proxy Integration For specific geographic markets, we use a standalone Nginx server as a reverse proxy in front of Vercel to optimize connection speeds. To ensure that Vercel’s CDN and Cache layers function correctly in this setup, what are the mandatory configurations? Currently, we are passing:

  • Host (matching the Vercel deployment)

  • X-Forwarded-For / X-Real-IP

  • proxy_ssl_server_name on (for SNI) Are there specific headers (e.g., X-Vercel-Forwarded-For) or cache-key-related headers that must be preserved or modified to prevent the Edge Network from serving stale regional copies?

The domain troubleshooting guide can help with most custom domain configuration issues. You might be able to use that guide to solve it before a human is available to help you. Then you can come back here and share the answer for bonus points.

You can also use v0 to narrow down the possibilities.