Isolation at the Core

The Cloudflare Workers runtime is, at its heart, a security project. Running untrusted third-party code demands a sandboxing model that is both strict and scalable, because the platform hosts many thousands of guest applications on every machine, with rapid switching between them. The architecture relies on several layers of defense rather than a single point of trust.

V8, the JavaScript engine from Chrome, provides the foundational isolation. Code executes inside V8 "isolates," which prevent access to memory outside the isolate's own boundary, even within the same process. This lets the platform run many tenants inside a single process efficiently. Without this, edge compute would require a separate process per customer, drastically limiting capacity and cost viability.

Not every worker runs in a shared process, though. Certain features demand an extra layer of separation. For instance, when a developer attaches the devtools debugger to inspect a worker, that worker is moved into its own private process. The inspector protocol has historically been trusted only to the browser's operator and has not received the same security scrutiny as the rest of V8, so this hedges against potential bugs there. Process isolation also serves as a secondary safeguard against Spectre, discussed later.

Even within shared processes, the runtime is instantiated multiple times per machine in what are called "cordons." Each worker is assigned a trust level, and workers of low trust are not scheduled in the same process as those more highly trusted. A free-plan customer, for example, will not share a process with an enterprise customer. This provides defense-in-depth in case a zero-day vulnerability is found in V8.

At the whole-process level, an additional sandbox is applied. This "layer 2" sandbox leverages Linux namespaces and seccomp to block all filesystem and network access. The configuration is stricter than typical container engines because namespaces and seccomp are applied after the process has started but before any isolates are loaded. Since the Workers runtime has already fully loaded, the sandbox can use a completely empty mount namespace and block every filesystem-related system call. Container engines cannot take this approach because exec() requires disk access to start a guest program. Here, guest programs are not native binaries, so the constraint does not apply.

The layer 2 sandbox also prohibits direct network access. The process communicates only over local Unix domain sockets with other processes on the same system. All external communication passes through a mediator outside the sandbox. One such mediator, the "supervisor," is responsible for fetching worker code and configuration. When the sandbox encounters a new worker, the request includes the encryption key for that worker's code and attached secrets. The sandbox passes the key to the supervisor to retrieve the code, but it cannot enumerate known workers, request configuration it does not need, or access TLS keys for HTTPS traffic.

Complete isolation is useless without a way for workers to communicate with the outside world. The API layer defines precisely what a worker may do. The design follows capability-based security principles: since there is no filesystem API, there is no filesystem access. Should local file access ever be supported, each worker would receive a Directory object capability representing a private directory. Such an object would allow creating and opening files and subdirectories, but would not permit traversal to a parent. Implementation would be mediated by the supervisor through Cap'n Proto RPC, a capability-based protocol maintained by the Workers team.

Network access today is limited strictly to HTTP, both inbound and outbound. Outbound requests travel over a Unix domain socket to a local proxy service. That service enforces restrictions, verifying that a request is addressed to a public Internet service or to the Worker's zone origin server—never to internal services on the local machine or network. It adds a header identifying the originating worker so abusive requests can be traced and blocked. Inbound requests follow a similar path: they are received by an inbound proxy that handles TLS termination and determines which worker script should run. The Workers runtime never sees TLS keys. The request is then passed over a Unix domain socket into the sandbox.

V8 Bugs and the Patch Gap

Every sandbox technology has bugs, and isolates are no exception. The approach must assume future vulnerabilities and plan accordingly. V8 is a large attack surface, but it benefits from immense security investment because of its position as one of the most widely deployed sandboxes. Google runs fuzzing infrastructure and pays substantial bounties for V8 escapes, which helps minimize the danger of zero-days.

When a bug is reported and fixed, the patch is published in the open and released simultaneously to everyone. The critical window is the "patch gap"—the time between fix publication and production deployment. In browsers, this gap has historically been significant; Google recently reduced Chrome's gap from 33 days to 15 days.

Cloudflare holds an advantage because it controls the machines on which Workers runs. The build and release pipeline is nearly fully automated. The moment a V8 patch is published, systems automatically build a new Workers Runtime release. After a one-click sign-off from human reviewers, the release is pushed to production automatically. The patch gap is now under 24 hours: a V8 patch released during Munich work hours is typically in production before the end of the US work day.

Why Isolate Tenants in Processes When We Can Use V8 Isolates?

Spectre-vulnerability-@2x

Cloudflare Workers runs on V8, and the V8 team has been clear that V8 itself cannot defend against Spectre. Since Workers leans on V8 for its sandboxing, a common question is whether that leaves the platform exposed. It does not, because the Workers environment offers mitigation strategies that do not depend on V8's internals.

The Problem With Process Isolation at the Edge

Workers is engineered to execute code in every Cloudflare location — currently 200 worldwide and growing. The platform is meant to be accessible to everyone, not just large enterprises, which means it must support a huge number of tenants, many of them low-traffic.

A conventional serverless provider can handle low-traffic tenants by pinning them to a single machine, keeping one copy of the application loaded, and hosting a dozen tenants per box in a mega-datacenter. That centralization trades latency and bandwidth costs for economies of scale. Workers takes the opposite approach: every tenant runs in every location, and some locations are small enough that we must fit thousands of active tenants per machine, spinning up inactive ones on demand.

With that density, each guest gets only a couple of megabytes of memory — hardly space for a call stack, let alone a process. Context switching must also be extremely cheap. Many Workers handle an event only occasionally, and individual events often finish in under a millisecond. A single core can switch between thousands of tenants per second, with significant host–guest communication for each event. Running each tenant in its own process multiplies that overhead dramatically; strict process isolation can make CPU costs roughly 10x higher than when tenants share a process.

To keep Workers inexpensive, fast, and open to everyone, we need multi-tenancy within a single process.

Spectre and Why Patches Aren't the Answer

Spectre is a class of attacks where a malicious program tricks the CPU into speculatively computing with data it should not access. The CPU backs out and hides the results, but subtle side effects, like cache state, can leak bits of the secret.

Spectre matters for any multi-tenant compute platform. The closer tenants are — processes versus VMs, for instance — the harder specific mitigations become. Kernel and hypervisor patches can shield processes and VMs from each other, often at serious performance cost. Workers separates tenants with V8 isolates, not processes or VMs, so we cannot rely on OS or hypervisor patches to solve the problem.

The industry doesn't like to admit this, but nobody has fixed Spectre. Even heavyweight VMs remain vulnerable. The common approach is a game of whack-a-mole: researchers find a new vulnerability every few months, CPU vendors ship microcode, and OS vendors push patches. It is clear that many more vulnerabilities exist but haven't been publicized. Graduate students on a shoestring budget are uncovering these bugs; imagine what a well-funded agency could find.

Blocking known vulnerabilities individually is not enough. The goal must be to address the entire class.

The Timing Problem and Cascading Slow-Downs

Fundamentally, Spectre uses side channels to detect hidden processor state. Side channels rely on non-deterministic system behavior, which software environments usually try to eliminate. The one glaring exception is timing: deterministic execution is at odds with performance optimization, so most Spectre attacks measure time.

Some propose making timers inaccurate or noisy, but that only slows attacks down, not stops them. As long as a timer tracks real time, statistical techniques can filter out the noise. Many security researchers consider that the end of the story. But slow-downs can be powerful — when an attack gets slower, new techniques become practical to slow it down further. Chain enough of these together, and the attack becomes so slow that it is no longer interesting.

Cryptography takes exactly this stance on brute force: technically possible, but when it takes billions of years, we call it secure. The same logic applies to Spectre. The question is what measures we take to push attack times into meaninglessness.

Killing the Microsecond

The Workers sandbox starts from a deliberately narrow foundation: no native code. Customers can only upload JavaScript and WebAssembly, which V8 then compiles to actual machine code on Cloudflare's side. That extra pass matters because it means Cloudflare never has to run a program that was written against a specific CPU architecture. Native code brings with it not just instructions like CLFLUSH and RDTSC, but entire operating-system expectations that make it impractical for a host to restrict or virtualize those instructions. An abstract intermediate format keeps those options open.

Locks on the Clock

The first concrete mitigation targets the most basic requirement of a side-channel attack: a way to measure time. In Workers, Date.now() exists, but it does not return the current time. It returns the time at which the network message that triggered the Worker was received. While the Worker executes, that value is frozen.

let start = Date.now();
for (let i = 0; i < 1e6; i++) {
  doSpectreAttack();
}
let end = Date.now();

start and end are always identical; an attacker cannot use Date to time their own code. This measure actually predates public knowledge of Spectre by several months, having been added in mid-2017 out of general concern about timing side channels.

Multi-threading and shared memory are also disallowed. All processing for one event happens on a single thread, and even multiple Workers that handle the same request run sequentially on that same thread. The goal is to prevent attackers from constructing an implicit timer by racing threads.

Locking down local time sources does not eliminate remote timing. The HTTP client that triggers a Worker can still measure the round-trip time, though the noise of traversing the Internet makes such measurements unreliable. In adversarial testing with Spectre researchers, no working attack has been developed against the production Workers platform.

The absence of a proven attack is not treated as a reason to stop hardening. A common suggestion is to reset a Worker's global state between requests so that no data carries over, which would theoretically force an attack to restart repeatedly. That does not hold up: state can be parked with a conspiring client and returned in the next request. So the platform is moving on to stronger measures.

Isolation for the Suspicious

Any Spectre attack that might exist despite the above controls would take hours at best, and more likely weeks, to carry out. That gives the platform time to react. Attacks tend to generate pathological performance patterns, especially when run billions of times in a loop to overcome other mitigations. Those patterns show up in CPU performance counters.

The usual problem with flagging bad performance is false positives. Legitimate programs can behave pathologically too. But Workers does not need to kill or suspend a suspicious Worker — it can simply reschedule that Worker into its own process. That costs more overhead, which is why process isolation is not applied to every Worker by default. But for the small number of Workers that look suspicious, or that simply consume a lot of CPU per event (making the relative overhead of isolation smaller), moving them into their own process is cheap.

Once isolated, the platform can rely on the operating system's own Spectre defenses, in the same way desktop browsers do. Cloudflare has been developing this dynamic isolation approach with the team at Graz Technical University, which co-discovered Spectre and has since published a large share of the follow-on research. The system is in testing and expected to roll out within weeks.

Process isolation is not a complete defense against unknown future vulnerabilities. But the trend is that new Spectre variants are slower to exploit, so even unknown attacks are likely to be slowed substantially by isolation.

Shuffling the Deck Daily

Once dynamic process isolation is in place, only hypothetical unknown attacks remain a concern. Given the mitigations already in place and the slowdown trend of newer attacks, a reasonable guess is that any such attack would take days. On that timescale, another tool becomes available: restart the entire Workers runtime daily. That resets the location of everything in memory, forcing an attacker to rediscover where secrets live. Workers can also be rescheduled across physical machines and cordons, limiting the window during which any particular neighbor can be attacked.

Because Workers are preemptible in a way that containers and VMs are not, the platform has broad freedom to frustrate attacks. This work is described as an ongoing investment rather than a problem to be solved once.

Conclusion

A secure sandbox is only the starting point for a secure compute platform. Real-world security is not a matter of clever one-off fixes; it is the continuous work of building defenses incrementally thicker, layer by layer.