--- slug: multi-process-architecture type: decision summary: "The 2008 decision to run each renderer, GPU service, and network stack in its own OS process; every later Chromium security and performance pattern builds on the boundary this choice established." created: 2026-05-12 updated: 2026-05-13 last_link_verified: 2026-05-13 related: browser-renderer-split: relation: enables note: "The privilege asymmetry between browser and renderer is the trust model the multi-process boundary makes possible." site-isolation: relation: upstream-of note: "Site Isolation extends the process boundary from per-renderer to per-site, building on the architectural foundation this decision established." untrusted-renderer-axiom: relation: enables note: "Treating the renderer as hostile is only enforceable because an OS-enforced boundary separates it from the privileged browser process." stateless-ipc-interface: relation: enables note: "Cross-process IPC discipline is the operational consequence of separating renderer and browser into distinct OS processes." process-consolidation-memory: relation: refined-by note: "Process consolidation under memory pressure is the documented conditional relaxation of the per-renderer boundary." escape-chain: relation: enables note: "The sandbox-escape chain's link count is determined by how many boundaries an attacker must cross, and the process boundary is the central one." rendering-pipeline: relation: enables note: "The rendering pipeline's cross-process stages are a direct consequence of distributing the work across separate OS processes." intent-ship-pipeline: relation: governs note: "Web-platform feature proposals that would alter the process-trust model are reviewed against this decision through the Intent pipeline." --- # Multi-Process Architecture > **Decision** > > A one-time architectural or governance choice whose consequences still govern current work. *The 2008 decision to run each renderer, GPU service, and network stack in its own operating-system process. Every later security and performance pattern in Chromium builds on the OS-enforced boundary this choice established.* > "Each renderer process is sandboxed; the browser process restricts what each renderer process is allowed to do." > — Adam Barth, Collin Jackson, Charles Reis, and the Google Chrome Team, *The Security Architecture of the Chromium Browser* (2008) ## Decision Statement The Chromium project decided at inception to run the browser's components as separate operating-system processes (the privileged browser process, each renderer, the GPU service, and the network stack) rather than as threads inside a single address space. The OS, not Chromium, enforces the memory boundary between them. ## Context In 2006, when Chromium's design work began, the dominant browsers ran every tab, plugin, and component as threads in a single OS process. A bug in any JavaScript engine, image decoder, or CSS parser could corrupt the entire browser's memory; a hang in any tab could freeze every other tab; a renderer-resident plugin had the host process's full ambient authority. Crash rates were high enough that browser stability was a genuine product concern. The Chromium team, drawing on prior work at Microsoft Research (the OP browser project) and on the IRIX and OS X process models, had a clear set of design pressures to resolve: tab-level crash isolation, defense-in-depth against renderer-resident memory-corruption bugs, and a path toward exploit mitigation that did not depend on the renderer's source code being bug-free. The decision was made between 2006 and Chrome's public launch on 2 September 2008. It predates Site Isolation by ten years and predates the V8 heap sandbox by roughly fifteen, but every later isolation decision in the project rests on it. ## Alternatives Considered | Alternative | Description | Reason rejected | |---|---|---| | Single-process, multi-threaded | The Internet Explorer 6/7 and Firefox 2/3 model. One OS process; tabs as threads in a shared address space. | A memory-corruption bug in any component compromises the entire browser. A hang in any tab freezes the rest. No OS-enforced privilege boundary is available; sandboxing has to be implemented inside the address space and is consequently far weaker. | | Single-process, isolated heaps (in-language) | One OS process; per-tab heaps separated by a managed runtime or compiler-enforced memory regions. | Did not exist as a deployable platform for a C++ codebase in 2006. Even granting that it did, in-language isolation does not survive a C++ memory-corruption bug: a use-after-free in any code path reaches any heap. The whole point of moving the boundary into the OS was to defend against C++ memory bugs, not assume them away. | | Process-per-tab without privilege separation | Each tab in its own OS process, all running with the user's full authority. | Provides crash isolation but no security gain. A compromised renderer still has full file-system and network access. Crash isolation alone did not justify the cost. | | Process-per-tab with browser/renderer privilege split (chosen) | Each renderer is a separate OS process running with reduced OS privileges; a single privileged browser process holds the capabilities denied to renderers; renderers reach those capabilities only through validated IPC. | Achieves crash isolation, achieves the privilege split that makes web content's compromise survivable, and uses the OS's existing process-isolation machinery instead of reinventing it. | The internal review record for the choice is preserved in the project's 2008 technical report and in the launch-time public design documentation; the alternative-elimination logic above paraphrases the report's framing. ## Rationale Three properties of the chosen alternative carried the decision. **The boundary is enforced by the OS, not by the codebase.** A C++ memory-corruption bug in any renderer-resident component (image decoder, JavaScript engine, layout, CSS) can't read or write the browser process's memory, because the bug is constrained by the operating system's page tables. Defenses that rely on the C++ code being correct fail under any memory-safety bug anywhere in the binary. Defenses that rely on the OS fail only under a kernel bug. The kernel is far smaller, far more scrutinized, and far less frequently changed than renderer code; the move from in-process to out-of-process isolation trades a large attack surface for a small one. **Privilege is denied at process creation, not at API call.** The renderer is denied file-system access, network access, and child-process creation through the OS sandbox policy, applied when the renderer process is launched. An attacker who compromises a renderer doesn't encounter denial-by-policy at the moment they call an API; they encounter denial-by-syscall, because the OS rejects the call regardless of what code is running. The browser/renderer privilege asymmetry that the [*Browser-Renderer Privilege Split*](browser-renderer-split.md) concept names is the operational form of this principle. **Cross-process communication forces a validation choke point.** Every capability the renderer needs from the browser (opening a file, making a network request, decoding cryptographic material) has to pass through Mojo IPC, where the browser side can validate the request before honoring it. This is the architectural setup that makes the [*Untrusted Renderer Axiom*](untrusted-renderer-axiom.md) tractable: there's exactly one boundary at which the browser inspects renderer-supplied data, not many scattered defensive checks. The cost (roughly 50–100 MB of additional resident memory per renderer process on desktop, plus the latency of IPC for every cross-boundary call) was judged acceptable in exchange for those three properties. ## Ongoing Consequences The decision did not so much establish a pattern as establish a substrate. Every subsequent architectural and security decision in Chromium either depends on it or is a refinement of it. For every contributor and every contribution, the consequences are concrete. Code that runs in a renderer must assume it has no file-system access, no network access, and no ability to create child processes; reaching any of those capabilities requires a Mojo IPC call to the browser and a validation check on the browser side. Code that runs in the browser process must assume any IPC message from a renderer may be hostile. A renderer can be compromised by any malicious JavaScript page it loads, and the browser can't tell which messages come from a compromised renderer and which do not. The [*Stateless IPC Interface*](stateless-ipc-interface.md) pattern, the [*Untrusted Renderer Axiom*](untrusted-renderer-axiom.md) concept, and the [*IPC Integer Type Discipline*](ipc-integer-discipline.md) pattern are all direct prescriptions for code at the boundary. For security response, the decision determines the structure of exploit chains. A full sandbox escape requires defeating multiple boundaries in sequence (a memory-corruption primitive inside the renderer, a V8 heap-sandbox bypass to escape the in-process containment, and a Mojo IPC bug to cross from renderer to browser), because each boundary is enforced by a different mechanism. The [*Sandbox Escape Chain*](escape-chain.md) concept names the three-link structure that the multi-process decision is the largest link of. For performance, the decision creates a cost the project has had to manage continuously. Each renderer carries process-creation overhead, per-process memory overhead, and cross-process IPC latency. The [*Rendering Pipeline*](rendering-pipeline.md) is shaped by which work the architecture distributes across processes and which it keeps within one; the [*Process Consolidation Under Memory Pressure*](process-consolidation-memory.md) pattern documents the conditional relaxation on lower-memory hardware. Site Isolation, when it shipped in 2018, increased the number of renderer processes and consequently the memory cost: the project paid roughly ten to thirteen percent of desktop memory to extend the boundary from per-tab to per-site. For governance, the decision is load-bearing for the Intent pipeline. A proposed web-platform feature that would weaken the process boundary (for instance, by letting one origin read another origin's memory without IPC validation) is reviewed against the substrate this decision established. The [*Intent to Ship Pipeline*](intent-ship-pipeline.md) treats compromises to the process trust model as load-bearing review concerns. ## Reversal Conditions The decision is effectively permanent. Three things would have to be true for it to be revisited. The OS process model would have to be replaced by something stronger at comparable cost. A capability-secure OS or a hardware-enforced memory-tagging architecture deployed at scale could, in principle, provide the security properties the multi-process decision exists to deliver at lower memory cost. CHERI, ARM MTE, and similar work are watched in this register; none currently displaces OS processes as the boundary. The cost calculus would have to invert. If per-process memory overhead became the dominant platform constraint (for instance, on a future device class with total memory far below current Android low-memory thresholds), the project would face pressure to relax the boundary structurally rather than conditionally. The current response is the conditional relaxation pattern, not a structural reversal. A fundamentally different threat model would have to obtain. The decision is calibrated against a threat model in which renderer-resident memory-corruption bugs are an ever-present risk. If that threat model dissolved (for instance, through a project-wide migration to a memory-safe systems language that the project trusted across the renderer codebase), the architectural justification would weaken. The work on incrementally adopting Rust in selected renderer components is in progress; it doesn't yet approach the scale at which the multi-process boundary would be the wrong tool. None of these conditions is close. The project treats the multi-process boundary as a permanent feature of its architecture, and reasoning that assumes the boundary will hold is the default register for design discussion across security, performance, and governance. ## Notes for Agent Context An AI coding agent working on Chromium code must hold the process-boundary model explicitly. Code in `content/renderer/`, `third_party/blink/renderer/`, or any file under a `renderer/` path runs in an unprivileged process: no file-system access, no network access, no ability to spawn child processes. Every such capability has to come through a Mojo IPC call to a browser-process service. Code in `content/browser/`, `chrome/browser/`, or any browser-side IPC handler must treat every renderer message as potentially hostile and validate every field, regardless of what the renderer claims to have validated. Never propose a design that "lets the renderer call the OS directly" or "skips IPC validation because the renderer just validated the same field"; both are direct violations of the architecture this decision established. When asked which process a piece of code runs in, the answer comes from the directory it lives in and the BUILD.gn target it compiles into, not from runtime behavior. ## Sources The canonical primary source is the Chromium project's own design documentation: `docs/multi-process-architecture.md` in `chromium/src`, the authoritative description of the architecture's intent and structure, updated in place as the project evolves. The founding citation is the 2008 technical report *The Security Architecture of the Chromium Browser* by Adam Barth, Collin Jackson, Charles Reis, and the Google Chrome Team, which sets out the rationale, the alternatives considered, and the threat model the architecture defends against. The public announcement was the Chrome launch blog post of 2 September 2008, which framed the architecture as a stability-and-security choice for end users. Reis, Moshchuk, and Oskov's 2019 USENIX Security paper *Site Isolation: Process Separation for Web Sites within the Browser* documents the later refinement of the per-tab boundary into a per-site one and reports the memory-overhead measurement that calibrates the architecture's ongoing cost. ## Technical Drill-Down - [`docs/multi-process-architecture.md`](https://chromium.googlesource.com/chromium/src/+/main/docs/process_model_and_site_isolation.md) — current design documentation for the process model and site isolation; the entry point for source-tree readers. - [`content/browser/`](https://chromium.googlesource.com/chromium/src/+/main/content/browser/) — browser-process code; every file here runs in the privileged process and is responsible for IPC validation. - [`content/renderer/`](https://chromium.googlesource.com/chromium/src/+/main/content/renderer/) — renderer-process code; everything here runs unprivileged and reaches OS capabilities only through Mojo IPC. - [*The Security Architecture of the Chromium Browser*, Barth, Jackson, Reis, and the Google Chrome Team (2008)](https://seclab.stanford.edu/websec/chromium/) — the founding technical report; the alternative-elimination logic and threat model are presented in their original form. - [*Site Isolation: Process Separation for Web Sites within the Browser*, Reis, Moshchuk, Oskov, USENIX Security (2019)](https://www.usenix.org/conference/usenixsecurity19/presentation/reis) — the later refinement; measured memory overhead and Spectre motivation are in §3 and §6. - [Chrome launch blog post, 2 September 2008](https://blog.google/products/chrome/welcome-to-chrome/) — the original public announcement; the stability-and-security framing for the architecture's first audience. --- - [Next: Site Isolation](site-isolation.md) - [Previous: The Process Trust Model](process-trust-model.md)