Cloudflare Worker failover
The Sprey v1 website uses a Cloudflare Worker instead of paid Cloudflare Load Balancing:
visitor -> sprey.win -> Cloudflare Worker -> primary WordPress VPS \-> sprey-outage.pages.dev on failureThe Worker attempts primary for every request. A network failure, five-second timeout, or configured upstream origin failure causes that request to receive the static outage page. Every later request tries primary again, so the site returns automatically after the VPS recovers.
Configured status coverage is currently:
502 503 504 520 521 522 523 524 525 526This is request-time failover. It does not run periodic probes, share health state between requests, or discover an outage before a visitor arrives. The static page is only an outage notice. It cannot preserve or provide WooCommerce cart, checkout, accounts, orders, sessions, or payment flows.
Prerequisites
Section titled “Prerequisites”sprey.winis an active Cloudflare zone and its WordPress DNS record is proxied.- The primary VPS already serves valid HTTPS through Caddy.
- Cloudflare SSL/TLS mode is Full (strict).
sprey-outage.pages.devserves the approved static outage page.- Cloudflare cache rules bypass dynamic WordPress and WooCommerce traffic.
- The current Workers Free request and CPU limits cover expected traffic.
Use a Workers Route when the Worker runs before the external WordPress application server.
Worker implementation
Section titled “Worker implementation”The canonical source is cloudflare/failover-worker.js in Sprey WP Stack.
The Worker:
- preserves the original request method, body, path, query, headers, and cookies when calling primary;
- makes exactly one primary attempt;
- fails over only for network errors, the explicit timeout, and the configured failure-status set;
- cancels an unused failed-origin response body before fetching fallback;
- fetches the static outage document with
GETorHEAD; - returns fallback as HTTP
503withCache-Control: no-store,Retry-After: 60, and anX-Sprey-Failoverdiagnostic header; - returns a small plain-text
503if both primary and fallback fail.
Do not add arbitrary application-level 500 responses without review. Broad failover can hide useful WordPress or WooCommerce diagnostics.
Test on a separate hostname
Section titled “Test on a separate hostname”When the production storefront must remain uninterrupted, use a temporary hostname such as failover-test.sprey.win:
- Add a proxied DNS record for the test hostname that resolves to the same WordPress VPS.
- Configure Caddy to accept the test hostname and verify its certificate.
- Add
failover-test.sprey.win/*to the Worker’s Domains & Routes. - Verify representative pages, assets, redirects, cookies, login, cart, and checkout.
- Confirm healthy responses do not contain
X-Sprey-Failover. - During a controlled maintenance window, create a handled failure.
- Confirm the Worker returns the static page with HTTP
503andX-Sprey-Failover: static-outage-page. - Restore primary and confirm the next request returns WordPress without a DNS change.
Remove temporary DNS/Caddy/Worker-route configuration after testing if it is not meant to remain deployed.
Verified failover behavior
Section titled “Verified failover behavior”The production route has been verified directly on sprey.win for full-origin outages and the controlled 525 TLS-handshake path. A dedicated proxied test hostname using the same Worker was used to verify the controlled 526 invalid-origin-certificate path without disrupting the production storefront.
Verified behavior includes:
- healthy origin traffic returned HTTP
200through Caddy with noX-Sprey-Failoverheader; - stopping Caddy produced Cloudflare
521; - handling
521returned the static outage page as HTTP503withCache-Control: no-store,Retry-After: 60, andX-Sprey-Failover: static-outage-page; - starting Caddy restored the next request to normal WordPress service without a DNS change;
- the same failover-and-recovery behavior was verified during a normal VPS reboot and a VPS hard reboot;
- a controlled TLS-handshake failure was created by stopping Caddy and temporarily binding a non-TLS listener to origin port
443, verifying the configured525path end to end; - for
526, Cloudflare Full (strict) was used on an isolated proxied test hostname; Caddy was stopped and a temporary TLS listener with a self-signed certificate was bound to origin port443; a direct origin connection established TLS successfully, while Cloudflare rejected the invalid certificate; - the Worker returned the static outage page for that invalid-certificate path as HTTP
503withCache-Control: no-store,Retry-After: 60, andX-Sprey-Failover: static-outage-page; - removing the temporary listener and restarting Caddy restored the next proxied request to normal WordPress as HTTP
200without the failover header.
TLS-specific 525/526 boundary
Section titled “TLS-specific 525/526 boundary”Both TLS-specific paths in the configured failure set are now explicitly verified end to end:
525— TLS handshake failure at the origin path;526— TLS connection succeeds, but Cloudflare Full (strict) rejects the invalid/self-signed origin certificate.
In both cases, the Worker served the Sprey static outage page instead of exposing Cloudflare’s default TLS error page, and normal WordPress service returned on the next request after the origin was restored.
Cache boundaries
Section titled “Cache boundaries”Failover does not make dynamic commerce content safe to cache. Bypass cache for at least:
/cart*,/checkout*, and/my-account*;/wp-admin*and/wp-login.php*;- WooCommerce Store API, REST API, AJAX, and webhook endpoints as applicable;
- authenticated requests and requests with WordPress or WooCommerce cart/session cookies.
Validate and roll back
Section titled “Validate and roll back”curl -sS -D - -o /dev/null https://sprey.win/Normal WordPress responses have no X-Sprey-Failover header. Controlled failover returns HTTP 503 and either static-outage-page or fallback-unavailable in that header.
To roll back, remove or disable only the relevant Workers Route. Do not change DNS.
For operational diagnosis and incident handling, use WP Stack failover operations.