Failure domains and resilience
Where the SLA boundary actually sits, what fails independently, the blast radius of each failure, and the degradation patterns that keep an app useful when a storage binding is slow rather than returning errors.
Designing for this platform means designing for partial failure, because the parts fail independently and are guaranteed independently.
Where the SLA boundary actually sits
Cloudflare commits to a 99.99% monthly uptime SLO for Workers. The exclusions are what an architect needs to see:
The Service Level Objective does not apply to unavailability resulting from "…incorrect configuration of bindings (e.g., KV, Durable Objects, D1, or R2, etc.), mismanaging Workers secrets, or exceeding resource limits" or from "unavailability or performance degradation of interdependent Cloudflare services" including the CDN, DNS, WAF, and storage bindings.
Drawn as a picture:
Two conclusions follow, and they shape everything else here:
- "The platform is up or down" is not a model that exists. Plan for the case where compute is healthy and one store is slow.
- Your own configuration is inside your responsibility. A misconfigured binding, a mismanaged secret, or exceeding a documented limit is not a platform failure — which makes change management part of your availability story.
Spikefrost's own commitment sits at 99.9% monthly uptime for app serving, deliberately beneath Cloudflare's compute figure to leave headroom for the excluded bindings and our control plane. Full terms in SLAs, limits and quotas.
The failure domains
| Domain | Blast radius | Detected by | Your mitigation |
|---|---|---|---|
| A single Cloudflare location | Requests routed there, briefly | Nothing to do — automatic | None needed; reroute is automatic |
| The CDN / edge cache | Cache misses; all traffic reaches your Worker | Traffic spike into the isolate, x-sf-cache |
Ensure the app survives 100% miss traffic |
| Your Worker code | That route, or all routes | 5xx in request logs | Rollback; guard rails in code |
| D1 (your app's database) | Every route that queries it | Errors or latency in logs | Timeouts, cached reads, queued writes |
| A single Durable Object | Only that key's clients | WebSocket errors for that room | Retry with backoff on the client |
| KV | Cached lookups and flags | Fallback path exercised | Always code a default |
| R2 / assets | Media and file downloads | 5xx on asset URLs | Assets are cached at the edge already |
| The Spikefrost control plane | Deploys, CLI, agent dispatch. Not app serving | Deploy failures | None needed to keep serving traffic |
The last row is worth stating explicitly to enterprise reviewers: a control-plane incident does not stop your deployed app from serving traffic. Your Worker and its bindings keep running; what you temporarily lose is the ability to ship changes.
The Durable Object row is the one people misread. Failure is scoped to one object, not the class — a problem with room-42 leaves the other hundred thousand rooms untouched. That granularity is a resilience feature, and it argues for many small objects over one large one.
Degrade, don't fail
The difference between an incident and an outage is usually whether the application was written to degrade.
Four patterns that carry most of the weight:
Cache the read paths that can be cached. A cached route keeps serving when the database is unreachable, because it never touches it. This is the highest-leverage resilience work available and it's a one-line change per route — see Routing and pages.
Bound every dependency. Wrap a database or external call in a timeout and decide what to serve when it expires. Unbounded waits turn one slow store into a queue of stuck requests, which is how partial degradation becomes total.
Queue writes instead of dropping them. If accepting an order matters more than processing it this second, put it on a queue and acknowledge. The customer succeeds; the work drains when the store recovers.
Keep a kill switch in KV. A flag read on the hot path lets you disable an expensive feature in seconds with no deploy:
const heavyEnabled = (await c.env.KV.get('feature:recommendations')) !== 'off';
During an incident, seconds matter and a deploy is a minute. Flags are the fastest mitigation you have.
Mitigations, ordered by speed
| Mitigation | Time to effect | Use when |
|---|---|---|
| KV feature flag | Seconds | An expensive or broken feature needs disabling |
| Maintenance mode | Seconds | The app must stop serving traffic entirely |
| Firewall rule / blocked path | Seconds | Abuse or a hot path needs blocking before your code runs |
Code rollback (sf deploy --commit @1) |
~1 minute | A deploy caused it |
| D1 point-in-time restore | Minutes | Data was corrupted |
| Fix forward | As long as it takes | Everything else |
Maintenance mode and firewall rules act before the isolate runs, so they work even when your code is the problem — worth remembering when the failing path is the one you'd need to deploy through.
What this platform does not give you
Stated plainly, because discovering it during procurement is worse:
- No cross-provider failover. If a Cloudflare-wide event occurs, an app here is affected. Provider redundancy means running a second implementation elsewhere, which is a decision above this platform.
- No control over data residency via compute placement. Code runs wherever the request lands. See Isolation and tenancy.
- No point-in-time recovery outside D1. Durable Object and KV state cannot be rewound — see Durability and recovery.
- No long-running processes to hold a warm connection or retry loop between requests. Use queues and schedules.
If any of these is a hard requirement, tell us before you build rather than after. We would rather lose a deal early than fail an architecture review late.
Next
- Change management and rollback — shipping without becoming your own failure domain.
- Observability and audit — noticing before your customers do.
- SLAs, limits and quotas — the commitments in full.
Frequently asked questions
Does the 99.99% Workers SLO cover our whole application?
No, and this is the most important thing on this page. Cloudflare's Workers SLO covers the compute path and explicitly excludes the availability of storage bindings — D1, Durable Objects, KV, and R2. Compute and state do not fail together and are not guaranteed together.
What happens if a Cloudflare location goes offline?
Traffic reroutes to the next nearest location automatically. Because every location runs your code and holds no unique state, there is no failover to orchestrate and no region-level runbook to write.
What if the database is slow rather than down?
That's the more common and more dangerous case. Because D1 executes queries serially, a slow query delays every request behind it — so partial degradation looks like a site-wide slowdown. Timeouts and cached read paths are the mitigations.
Can we fail over to another provider?
Not within the platform. If provider-level redundancy is a hard requirement, an app on Spikefrost is one tier of your architecture rather than all of it — tell us early so nobody discovers the constraint late.
What's the fastest mitigation during an incident?
A feature flag in KV changes behavior in seconds with no deploy. Maintenance mode and firewall rules act before your code runs. A code rollback is about a minute. Choose by what's broken.