Cloudflare: Workers Failover
1. Overview
A Cloudflare Worker sits in front of the application. It normally proxies traffic to the Primary Origin. If the Primary Origin returns a 5xx error (Server Error) or encounters a Network Failure (Timeout/Unreachable), the Worker automatically reroutes the request to the Failover Origin.
Crucially, this system preserves the primary domain in the user’s browser, even when serving content from the failover server.
2. Architecture & Logic
- Intercept: Worker catches the request to the primary domain
- Health Check: Attempts to fetch from Primary.
- Failover Condition: If status >= 500 or a Network Error occurs:
- The worker fetches content from the failover domain.
- Worker injects a Secret Key header (
X-Failover-Secret).
- Identity Masking:
- Failover server detects the Secret Key in
wp-config.php. - It forces WordPress to set
HTTP_HOSTandWP_HOMEto the primary domain. - This prevents WordPress from triggering a Canonical Redirect loop.
- Failover server detects the Secret Key in
3. Example Configuration Details
| Setting | Value |
| Primary Domain | punkcake.net |
| Failover Domain | failover.punkcake.net |
| Failover Secret | pk_failover_8x92mKLD72hs9 |
| Trigger Route | punkcake.net/* |
4. Implementation Code
A. Cloudflare Worker Script
Location: Cloudflare Dashboard > Compute & AI > Workers & Pages > Create Application > Start with Hello World > Name the worker > Edit Code & Paste Below
export default {
async fetch(request, env, ctx) {
const CONFIG = {
// Change to primary domain
PRIMARY_HOST: 'punkcake.net',
// Change to failover domain
FAILOVER_HOST: 'failover.punkcake.net',
// Change to the secret you want
FAILOVER_SECRET: 'pk_failover_8x92mKLD72hs9'
};
try {
// 1. Try Main Site
const response = await fetch(request);
// 2. If Main Site is broken (500 errors), switch to failover
if (response.status >= 500) {
console.log(`Primary Failed (${response.status}). Switching.`);
return await serveFailover(request, CONFIG);
}
// 3. Otherwise return main site
return response;
} catch (error) {
// 4. If Main Site is unreachable (Network Error), switch to failover
console.log("Primary Network Error. Switching.");
return await serveFailover(request, CONFIG);
}
},
};
async function serveFailover(originalRequest, config) {
const url = new URL(originalRequest.url);
url.hostname = config.FAILOVER_HOST;
const failoverRequest = new Request(url.toString(), originalRequest);
// Set the Host so Nginx accepts it
failoverRequest.headers.set('Host', config.FAILOVER_HOST);
// Send the Secret Key (This is what triggers wp-config.php now!)
failoverRequest.headers.set('X-Failover-Secret', config.FAILOVER_SECRET);
try {
const response = await fetch(failoverRequest);
// Rewrite headers to prevent redirects
const newResponse = new Response(response.body, response);
const locationHeader = newResponse.headers.get('Location');
if (locationHeader) {
// If failover tries to redirect to "failover.punkcake.net", fix it to "punkcake.net"
const fixedLocation = locationHeader.replace(config.FAILOVER_HOST, config.PRIMARY_HOST);
newResponse.headers.set('Location', fixedLocation);
}
newResponse.headers.set('X-Served-By', 'Failover-System');
return newResponse;
} catch (error) {
return new Response("Service Temporarily Unavailable", { status: 503 });
}
}
B. WordPress Configuration (wp-config.php)
Location: Failover Environment > /wp-config.php
Placement: Must be at the very top, immediately after <?php.
/**
* CLOUDFLARE FAILOVER LOGIC
* Detects Secret Key from Worker and forces Main Domain Identity
* Make sure the secret matches one set in the worker
*/
if (isset($_SERVER['HTTP_X_FAILOVER_SECRET']) && $_SERVER['HTTP_X_FAILOVER_SECRET'] === 'pk_failover_8x92mKLD72hs9') {
// 1. Force Host Identity
// Makes WP believe the request is for the main domain
$_SERVER['HTTP_HOST'] = 'punkcake.net';
$_SERVER['SERVER_NAME'] = 'punkcake.net';
// 2. Force Protocol
$_SERVER['HTTPS'] = 'on';
$_SERVER['SERVER_PORT'] = 443;
// 3. Override URL Constants
// Prevents WP from redirecting based on database values
define('WP_HOME', 'https://punkcake.net');
define('WP_SITEURL', 'https://punkcake.net');
}
B. Assign Worker to the Route
In Cloudflare, click on your main domain > Workers Routes > Add Route
Make sure that the route is domain.com/* to cover all the pages and assign the right worker

5. Troubleshooting & Verification
How to Verify Failover is Working
You do not need to crash the main server to test this.
- Edit the Worker: Edit the worker from 500 responses to 200
if (response.status >= 200) - Visit Site: Go to the main domain.
- Inspect Headers: Open Chrome DevTools -> Network -> Click document request.
- Look for Response Header:
X-Served-By: Failover-System - Ensure the URL in the browser bar remains the primary domain.
- Click internal links (About, Contact) to ensure they do not redirect to the failover server.
- Look for Response Header:
Common Issues
- Redirect Loop: Usually caused if the code in
wp-config.phpis placed too low (afterwp-settings.phpis loaded). It must be at the top. - 500 Error: Check for syntax errors in
wp-config.phpor use of WordPress functions (likeadd_action) which are not available at that stage of loading.
Found this useful?
There's more where that came from — explore the rest of the documentation, experiments, and production work.
→ Back to the index