
You've got a dozen tabs open at once: one with an online document, one streaming a video, one logged into your company's admin panel, and one shopping site that's still loading — and now it's spinning and frozen.
Common sense says a browser is "one program," and if one program freezes, the whole thing should die with it. But strangely, only that one tab is stuck. The video keeps playing, the document keeps saving, and once you close the frozen tab, everything is back to normal.
Now try the opposite experiment: open a tab's console and type while(true){}. The moment you hit Enter, the page goes rigid — buttons won't click, text won't select, the scrollbar won't budge. Yet the tab next to it carries on as if nothing happened.
Both are "one page misbehaving" — so why does one drag down the whole browser and the other only itself? And how does the browser manage to keep every tab "safe on its own"? The answer lies in the browser's multi-process architecture. Understand it, and you'll know where the "main thread" we'll discuss later actually lives — and why it matters so much.
Shift + Esc), this will feel more concrete.Let's answer a question that sounds silly at first: is a browser one process?
Intuitively, yes — you double-click an icon, a program launches, so of course it's one process. But that intuition is wrong. A modern browser (Chrome, Edge, Firefox alike) is a collection of processes, not a single one. The window you see is actually painted cooperatively by several processes.
Why make it so complicated? Before answering "why," let's look at "what" this architecture looks like — and the best way to understand it is to start from how it "used to be," because multi-process was forced into existence by the pain of single-process.
Before 2008, browsers were basically single-process: networking, rendering, JavaScript, plugins, and UI all crammed into one process.
The biggest problem with a single process is that everything rises and falls together:
All these pains point to one conclusion: different pages ought to be isolated from each other. And the process, it turns out, is the most natural "isolation unit" the operating system provides — processes don't share memory, and a crash in one doesn't touch the rest. And so the multi-process architecture was born.
Using Chrome as an example, a modern browser consists mainly of these processes:
| Process | Responsibility | Plain analogy |
|---|---|---|
| Browser Process | The controller: address bar, bookmarks, back/forward, and the creation/destruction of all other processes | "Headquarters" |
| Renderer Process | Everything inside a site/tab: parsing HTML/CSS, running JS, layout, painting | "The workshop" |
| GPU Process | Handles GPU tasks submitted by all processes (compositing, rasterization) | "The dedicated GPU driver" |
| Network Process | Handles network requests (DNS, TCP, TLS, HTTP cache) | "Procurement" |
| Utility/Plugin Process | PDF viewing, audio decoding, plugins, and other chores | "Logistics" |
The two that matter most are the browser process and the renderer process. The browser process handles the "outside" (UI and coordination); the renderer process handles the "inside" (the life and death of one specific web page). And the "main thread" we care about lives inside the renderer process.
A renderer process contains more than one thread. Roughly:
transform animations.Note one critical fact: the main thread is single-threaded. That means "running JS" and "rendering the page" both queue up for the same worker. That's why a single while(true){} can freeze an entire page — the main thread is fully occupied by JS, and style, layout, and paint can't get a turn.
But hold on — don't rush into this. The main thread and event loop deserve their own article, next. For now, just remember: the main thread lives in the renderer process, is the shared home of both JS and rendering, and there's only one of it.
We've already laid out the pain; here are the three reasons summarized:
Here's a common misconception: "one tab = one renderer process."
Early Chrome was close to this (one process per tab), but later Site Isolation made the rule more precise: the unit of isolation is the site, not the tab.
The main motive is security: the 2018 Spectre vulnerability exposed the risk that different sites sharing a process could read each other's memory. Site Isolation is designed to close that hole at the root — data from different sites simply never lives in the same process.
As an aside: this is why you'll see "a few tabs mapping to several processes" — a single page's main document, its ad iframe, and its payment iframe may each get their own renderer process.
Processes have isolated memory, so how do they cooperate? Through IPC (Inter-Process Communication).
For example, when a renderer process wants the browser process to make a network request, read the clipboard, or pop up a system dialog, it can't just do it (the sandbox forbids it). It has to send a message via IPC to the browser process, ask it to do the job, and then receive the result back.
IPC comes at a cost: cross-process communication is far slower than an in-process function call (it involves serialization, message queues, and kernel context switches). This is why the browser tries to keep related tasks within the same process — the finer you slice the processes, the more IPC overhead you add. So "multi-process" and "low overhead" are a trade-off to balance.
Once you understand this architecture, a lot of "mysterious behavior" has an answer:
Open the browser's task manager
In Chrome, press Shift + Esc. You'll see a list: every tab, every extension, the GPU process, and the network process each on their own row, with independent CPU and memory usage.
Observe: do your open tabs map one-to-one to the "tab" rows in the list? Does any single page use an unusually large amount of memory?
Freeze exactly one tab, on purpose
Open two tabs, and in one of them type this into the console:
while (true) {}Switch to the other tab — it works perfectly. Switch back to the infinite-loop tab — nothing responds. This is the direct, hands-on feeling of "the main thread is fully occupied."
Observe Site Isolation in action
Open chrome://process-internals (or the equivalent page in a newer browser), find a page that embeds a cross-site iframe, and check whether the main document and the iframe are assigned to different renderer processes.
Cross-check with the system monitor
Open macOS's Activity Monitor or Linux's htop and search for browser-related processes. You'll see a bunch of similarly-named processes — those are the "workshops" of the multi-process architecture. Match them against the browser's task manager to verify the correspondence.
This article built the "map": you now know the main thread lives in the renderer process and that it's single-threaded. But what does "single-threaded" actually mean? Who decides what the main thread does first and next? Why does a while(true){} freeze the page while setTimeout and Promise don't?
These questions all belong to the event loop. In the next article, we'll dive inside the main thread to see how it's scheduled, why it can only do one thing at a time, and the full lifecycle of "a frame" from input to screen.