Back to Blog
Cloud NativeJuly 2, 20264 min read

Multi-Region Failover: Syncing Vercel Deployments with Cloudflare

Learn how to implement multi-region failover by syncing Vercel deployments with Cloudflare Workers and KV for near-instant disaster recovery.

cloudflare workersverceldisaster recoveryedge computingdevopssystem architectureCloudflareDeployment

When Vercel’s US-East region started throwing 503s during a high-traffic event last quarter, I realized my "high availability" strategy was mostly wishful thinking. I needed a way to shift traffic to a secondary region—or a completely different provider—without manual DNS propagation delays.

Implementing multi-region failover using Cloudflare Workers as a traffic controller is the most robust way to handle this. By decoupling your routing layer from your hosting layer, you gain the ability to steer requests based on real-time health checks, not just static DNS records.

The Architecture of Resilience

The goal is to keep your Vercel deployment as the primary origin while maintaining a "hot standby." If the primary origin returns an error, the Cloudflare Worker intercepts the request and routes it to the secondary origin.

We use Cloudflare KV to store the current status of each region. Because KV is globally replicated, a change to the "health" key propagates to all edge nodes in roughly 200ms to 500ms, effectively acting as a global toggle switch.

Flow diagram: User → Cloudflare Worker; Cloudflare Worker → Cloudflare KV; Cloudflare Worker → Vercel Primary; Cloudflare Worker → Vercel Secondary; KV -- Status → Cloudflare Worker; V1 -- Health Check → Cloudflare KV

Why We Moved Away from DNS-based Failover

Initially, we tried using Cloudflare Load Balancing with DNS-based health checks. It failed us because of ISP caching. Even after we updated the DNS record to point to the secondary region, users in some parts of the world were still hitting the dead Vercel instance for hours.

We needed something that ran on every request. By moving the logic into a Cloudflare Worker, we ensure that every single request is validated against the current state stored in KV.

Implementing the Routing Logic

First, you need a worker that checks the KV status before deciding where to proxy the request. Here is a simplified version of what we run in production:

JAVASCRIPT
export default {
  async fetch(request, env) {
    const status = await env.REGION_STATUS.get("primary_region");
    const targetUrl = status === "healthy" ? "https://primary.example.com" : "https://secondary.example.com";
    
    const url = new URL(request.url);
    url.hostname = new URL(targetUrl).hostname;
    
    return fetch(url.toString(), request);
  }
}

This is basic, but you can enhance it by following the patterns I’ve documented in Cloudflare Workers Geo-Routing: Dynamic Traffic Steering for Vercel. If you're doing complex A/B testing or canary releases alongside failover, check out Edge-Side A/B Testing: Routing Traffic Between Vercel and Cloudflare Workers.

Managing State with KV

The beauty of this setup is how you trigger the failover. You don't need to redeploy your code. You simply update the KV value via the Cloudflare API:

Bash
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$NAMESPACE_ID/values/primary_region" \
     -H "Authorization: Bearer $TOKEN" \
     --data "unhealthy"

Once that key is set to "unhealthy," the worker logic kicks in, and traffic shifts instantly.

A Quick Comparison of Failover Methods

MethodLatencyPropagationComplexity
DNS FailoverHighMinutes/HoursLow
Anycast (Cloudflare)LowSecondsMedium
Worker-based LogicLowest< 500msHigh

What I’d Do Differently Next Time

If I were starting this from scratch, I would integrate the health checks directly into the Vercel edge runtime. While Vercel Edge Functions Cold Start Optimization with Cloudflare KV helps with performance, having a dedicated "heartbeat" service that automatically flips the KV flag would be safer than relying on a manual curl command during an incident.

Also, remember that multi-region failover is only as good as your data synchronization. If your Vercel database isn't replicated, failing over to a secondary region won't help if that region can't access your user data. We currently use a global database provider to keep state consistent across regions, which adds its own set of latency trade-offs.

It’s not a perfect system—there’s always a risk of "flapping" if your health check logic isn't dampened—but it’s significantly better than waiting for DNS to propagate while your users stare at a 503 screen.

FAQ

Does this increase latency for every request? Slightly. Fetching a key from KV adds a few milliseconds to the request lifecycle. However, if you use ctx.waitUntil for logging or caching the status in memory for a few seconds, the impact is negligible.

Can I use this for non-Vercel origins? Absolutely. The Cloudflare Worker doesn't care where the request is going. You could use this to failover between Vercel and an AWS S3 bucket or a custom VPS if needed.

What about SSL/TLS certificates? Since Cloudflare handles the edge termination, you just need to ensure your secondary Vercel deployment has a valid domain configuration. Cloudflare handles the handshake with the origin seamlessly.

Similar Posts