Browser architecture
Learn how browser, renderer, GPU, and network work fit together, why site isolation matters, and why a long script blocks a tab.
- 01Name the major jobsExplain what the browser, renderer, network, and GPU parts coordinate in Chrome.
- 02Reason about isolationPredict why a cross-site iframe can need a separate renderer process in Chrome.
- 03Protect responsivenessConnect one busy main thread to delayed input and know when compositing can still help.
A browser is more than one program
A browser is not one giant JavaScript runtime. It is an application that coordinates separate operating-system processes. A process has private memory. A thread is one path of work inside a process. Browsers use both boundaries so a page can be responsive, safer, and easier to recover when one part fails.
Browser architecture is the arrangement of processes and threads that turns page resources into an interactive screen. There is no browser-standard architecture. This lesson says in Chrome for Chrome-specific details; other browsers use similar but not identical designs.
Keep two scales separate. Processes divide large jobs and memory spaces. Threads divide work inside one process. Your page normally lives in a renderer process, but the browser also coordinates UI, networking, graphics, storage, extensions, and more.
This follows libuv & the thread pool. Node showed how one runtime coordinates I/O. Here the browser adds process boundaries around tabs and sites. The next lesson, What happens when you navigate, follows a URL through those boundaries.
Browser, renderer, GPU, and network work
In Chrome, the browser process owns the browser-facing parts: the address bar, tabs, navigation decisions, and privileged coordination. A renderer process turns HTML, CSS, and JavaScript into the document inside a tab. This split means page code does not directly own the browser UI or arbitrary file access.
const page = "shop.example";const iframe = "video.example";const siteIsolation = true; const renderers = siteIsolation && iframe !== page ? 2 : 1;console.log("renderers", renderers);Line 1 names the top document. Line 2 names an embedded frame from another site. Line 3 enables the model's isolation switch. Line 5 decides whether the model needs one or two renderer rows, and line 6 prints the count. With these two different sites it prints renderers 2.
Chrome also has a GPU process for graphics work, while networking is coordinated by the browser process and its services. Do not turn this into a fixed process count. Chrome can add utility and extension processes, reuse processes, or change implementation details based on the platform.
Why make this expensive split at all? A renderer receives complicated input from a page: HTML, CSS, images, scripts, fonts, and user events. Giving that work a restricted process means a renderer crash can often be handled as a tab problem. It also gives the operating system a place to apply a sandbox, which limits what an untrusted page process may ask the computer to do.
Processes must communicate, so separation is not free. Messages cross an inter-process communication boundary, and each process needs memory for its own work. Chrome balances those costs against stability and security. As a web developer, you normally do not choose Chrome's process reuse policy. You do benefit from understanding why DevTools can show several rows for one tab.
| Part | Plain job | Why it is separate |
|---|---|---|
| Browser process | Owns browser UI and privileged coordination | Starts navigation and coordinates other processes |
| Renderer process | Turns a document into an interactive page | Runs page JavaScript, parsing, style, layout, and paint work |
| Network service | Fetches requests and responses | Keeps network work separate from page JavaScript |
| GPU process | Handles graphics tasks in isolation | Receives frames for display |
Think of a browser as an apartment building. The building office manages the gate and lift, while each flat has its own family. A problem in one flat need not close the whole building.
- In real life: Building office runs the entrance
- In JavaScript: Browser process coordinates browser work
- In real life: Each flat holds one family
- In JavaScript: A renderer holds page work
- In real life: Power room serves the building
- In JavaScript: GPU work serves graphics
- In real life: A fire in one flat stays there
- In JavaScript: A crashed renderer need not crash the browser
Where the analogy stops: Real processes can be reused or split in ways an apartment building cannot show.
Site isolation
Site Isolation is Chrome's extra security boundary for documents from different sites. On desktop Chrome, cross-site documents, including cross-site iframes, are put in different sandboxed processes. It makes it harder for a compromised renderer to access sensitive data from another site.
A site is not the same thing as a full URL. Chrome describes it using scheme and registered domain, while ignoring subdomains, ports, and paths for this boundary. The exact rule has compatibility reasons. The useful mental model is simpler: a page and a truly different embedded site should not casually share one renderer memory space.
Site Isolation complements, rather than replaces, the same-origin policy. The same-origin policy is a web-platform rule about what scripts may read or change. Site Isolation adds a lower-level process boundary so that a renderer that handles one site receives much less data from another site. It is defense in depth: two defenses cover a case where one defense has a bug.
The boundary has a cost. More renderer processes can use more memory, and a page with several cross-site frames requires coordination between processes. That cost is intentional. It is also why an app should not infer security or performance behavior from a toy count alone. The playground teaches the direction of the decision, not a Chrome Task Manager contract.
const page = "shop.example";const iframe = "video.example";const siteIsolation = true; const renderers = siteIsolation && iframe !== page ? 2 : 1;console.log("renderers", renderers);sharedtabs, address bar, privileged coordination
sharedrequests and responses
sharedsubmits graphics work
shop.examplemain document
The model shows one renderer. Same-site frames can share it; turning Site Isolation off here is only a teaching contrast, not browser advice.
Try the same-site button first. The model has one renderer. Change only the iframe to cross-site while Site Isolation is on, and it adds a renderer. Turning the toggle off is a contrast for the model, not a recommendation to weaken browser security.
The renderer main thread
Inside a renderer, the main thread handles most page code. It parses HTML, runs ordinary JavaScript, calculates styles, lays out boxes, makes paint records, and runs event listeners. Web workers can run some JavaScript elsewhere, but a normal script tag and a normal click listener use this main thread.
const user = "Asha";console.log("Hello", user);Line 1 stores the page value. Line 2 runs on the main thread and prints Hello Asha. The example is deliberately small: the important fact is that normal code gets one main-thread turn, not a new thread for each line.
When the main thread is busy, it cannot also run a click handler, parse another piece of HTML, or make the next style and layout decision. This is why the word “main” matters more than a list of internal method names: it is the shared lane for work your page needs now.
Picture a user typing into a search box. The input event needs a turn on the main thread. Your listener might update state, change the DOM, and cause style and layout work before the next visual frame is ready. Each piece is ordinary work, but a long calculation in the middle makes the whole chain late. The browser cannot run the click listener halfway through a synchronous loop.
This does not mean every page should create workers. Short, clear synchronous code is usually easiest to maintain. The threshold is user experience: when work grows with the amount of data, can run for many milliseconds, or makes input visibly late, split it, defer it, or move suitable CPU work to a worker. Measure the page before adding machinery.
Why a slow script freezes a tab
A synchronous loop keeps control until it returns. During that time the main thread cannot run a waiting click handler. The browser can receive the click, but the page code that responds to it must wait for the current JavaScript task to finish.
const start = Date.now();while (Date.now() - start < 50) {}console.log("done after about 50 ms");Line 1 remembers a start time. Line 2 loops until about 50 milliseconds have passed. Line 3 prints done after about 50 ms. During those 50 milliseconds, this page could not respond to clicks because its main thread was still in line 2.
The exact elapsed time varies by device, so do not use this as a benchmark. The stable lesson fact is the order: synchronous JavaScript runs before later input handlers on that same main thread. A slow script often makes one tab feel frozen, even when other tabs and the browser UI remain alive.
This is a replay of instrumented lesson code, not a browser engine debugger. It shows why one long main-thread task makes input wait.
script
let finished = ""; function runNext() { finished = tasks.shift() ?? ""; return finished;} console.log(runNext());console.log(runNext());Let input between chunks
Some jobs are large but divisible: processing a long list, preparing a report, or updating many visible items. Instead of one unbroken task, do a small useful piece and yield. That gives the browser an opportunity to run input, rendering, and other pending work before the next piece.
const chunks = ["chunk 1", "click handler", "chunk 2"];const completed = []; for (const task of chunks) { completed.push(task);} console.log(completed.join(", "));Line 1 places a click between two chunks. Line 2 starts an empty completed list. Lines 4 and 5 record each turn. Line 8 prints chunk 1, click handler, chunk 2. This is a teaching model, not a promise that a particular browser API picks this exact order.
For CPU-heavy work that stays large, use web workers. A worker has a separate JavaScript execution context. Sending data has a cost, so first measure whether splitting or moving the work actually improves the interaction your users feel.
This replay models splitting a large job into turns. It does not promise a particular browser scheduling API or timing.
script
const completed = []; for (const task of chunks) { completed.push(task);} console.log(completed.join(", "));Compositor and raster threads
After the main thread decides what a page looks like, Chrome can prepare layers for compositing. The compositor thread combines those layers into frames. Raster threads turn prepared drawings, often in tiles, into pixels. The GPU then helps display the resulting frame.
const mainThreadBusy = true;const layerIsReady = true; const canScroll = mainThreadBusy && layerIsReady;console.log(canScroll ? "compositor can move layer" : "main thread work needed");Line 1 says the main thread is busy. Line 2 says an existing layer is ready. Line 4 checks both conditions. Line 5 prints compositor can move layer. It models the important exception: scrolling or an eligible layer animation can sometimes continue without waiting for main-thread JavaScript.
This is not magic. If an update needs new style, layout, or paint work, the main thread must participate again. Read the rendering pipeline for the full path from DOM and CSS to layers and pixels, and rendering performance for practical measurement.
A layer is useful when the browser can reuse its prepared pixels and change how that layer is placed or blended. Scrolling is the everyday example: the compositor can make a new frame using content that was already rasterized. Some transform and opacity animations can use the same route. The exact eligibility is an implementation decision, so treat it as a performance possibility to verify, not a CSS guarantee.
Raster work is still real work. Large images, text, shadows, and paint-heavy effects can need many pixels. The compositor chooses priorities and combines results, but it cannot display a future layer that has not been prepared. That is why a fast interaction often needs both: short main-thread work and a rendering path with little new layout or paint.
Practical choices
Start with the user-visible symptom. A click that reacts late usually points to busy main-thread work, not a missing extra renderer. A scrolling problem can involve main-thread event handlers, new paint work, or a layer that cannot be composited independently. A process model helps you ask better questions; a trace tells you which question is real.
- Keep input handlers short and defer non-urgent work.
- Split long calculations into small units when they can safely yield.
- Use a web worker for sustained CPU work that does not need DOM access.
- Use browser performance tools before assuming a process or thread is the cause.
- Prefer transform and opacity animation only after measuring the whole rendering path.
One slow renderer is usually contained to its tab or site process more than a single-process browser would be, but containment is not a performance feature. Your page still has a main thread with finite time. A page can be isolated and still be unresponsive to its own users.
Use a trace as a story, not just a score. Find the late interaction, then look for the task that was running immediately before it. If the task is JavaScript, inspect its input size and decide whether it can be reduced, chunked, or moved. If it is style, layout, or paint, inspect the DOM change and rendering work. A process diagram cannot replace this evidence.
Repeat the trace after a change. A fix is useful only when the interaction becomes faster for the same user action.
Be careful with quick fixes. Moving every calculation to a worker can create copying overhead and more complex state. Adding layers everywhere can increase raster and memory cost. Increasing work elsewhere does not make a blocked main-thread handler return sooner. The useful goal is not “use more threads”; it is “make the next user-visible response happen soon enough.”
- Handle the address bar
- Run a page click handler
- Calculate page style and layout
- Turn layer tiles into pixels
- Move an already-ready scroll layer
- Coordinate a network request
Sort each card by the part that most directly owns this job in the lesson's Chrome overview.
Common misconceptions
- “One tab means one process.” Chrome can use several processes for one tab, especially with cross-site frames.
- “Site Isolation makes every origin separate.” Its usual boundary is site, not every full origin or URL.
- “The compositor runs my JavaScript.” It combines ready layers; ordinary page JavaScript stays on the main thread.
- “A long script freezes the whole browser.” It commonly freezes its renderer's page work; other processes can continue.
- “GPU work fixes all jank.” New style, layout, or paint still needs the main thread.
| Term | What it means | Example |
|---|---|---|
| Process | Separate program with private memory | A renderer for one site |
| Thread | A path of execution inside one process | The renderer main or compositor thread |
| Site isolation | Chrome process boundary for cross-site documents | A cross-site iframe renderer |
| Compositing | Combines already-prepared layers into a frame | Scrolling a ready layer |
Practice exercises
In the playground's cross-site, isolated case, how many renderer rows appear?
console.log(2 + 1);The cross-site isolation model shows 2 renderer rows: one for shop.example and one for video.example.
Type the first work item printed by this model.
const order = ["script", "click"];
console.log(order.join(", "));It prints script, click, so the first text is script. A long script finishes before the queued click in this model.
What does the ready-layer model print?
const mainThreadBusy = true;
const layerIsReady = true;
console.log(mainThreadBusy && layerIsReady ? "scroll" : "wait");It prints scroll. This models a compositor moving a ready layer while main-thread JavaScript is busy.
Your page embeds a document from a different site. What kind of document does Site Isolation place in a separate process?
A cross-site iframe or document gets a separate renderer process in Chrome Site Isolation's model.
A dashboard recalculates thousands of rows after every keystroke. Name one safer response than one large synchronous loop.
Split the work into chunks when it can yield, or move sustained CPU work to a web worker. Both avoid one giant main-thread task.
A checkout button sometimes feels late. What should you inspect before guessing at a process or GPU fix?
Record a performance trace first. It shows whether a long task, layout, paint, or another cause is actually delaying the interaction.
Check your understanding
Use the lesson's model carefully: process boundaries protect and contain work, while one renderer main thread still decides when page JavaScript and most visual work can run.
Question 1 of 7In Chrome, what normally owns page JavaScript inside a tab?
Choose an answer to see the explanation.
Question 2 of 7What does this print?
Read the code, then predictconst page = "shop.example"; const iframe = "video.example"; console.log(page === iframe ? 1 : 2);Choose an answer to see the explanation.
Question 3 of 7What is Chrome Site Isolation for?
Choose an answer to see the explanation.
Question 4 of 7Why can a long script delay a click?
Choose an answer to see the explanation.
Question 5 of 7What does this model print?
Read the code, then predictconst busy = true; const ready = true; console.log(busy && ready ? "scroll" : "wait");Choose an answer to see the explanation.
Question 6 of 7What do raster threads do in Chrome's rendering overview?
Choose an answer to see the explanation.
Question 7 of 7Which response is usually best for a long user-visible calculation?
Choose an answer to see the explanation.
Key takeaways
- In Chrome, browser, renderer, GPU, and network work are coordinated across processes and threads.
- Chrome Site Isolation puts cross-site documents in separate sandboxed processes.
- The renderer main thread runs ordinary JavaScript, input handlers, and major rendering decisions.
- One long synchronous script delays later page input on that main thread.
- Compositor and raster threads can prepare and combine ready layers, but they do not replace main-thread style, layout, paint, or JavaScript.
- Measure a slow interaction before choosing chunking, workers, or rendering changes.
Remember the one-liner.
A browser can use many processes, but each page still has a main thread that must return before its next task can run.
Coming next: What happens when you navigate.