cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

Browser architecture

Learn how browser, renderer, GPU, and network work fit together, why site isolation matters, and why a long script blocks a tab.

By the end, you can
  • 01
    Name the major jobsExplain what the browser, renderer, network, and GPU parts coordinate in Chrome.
  • 02
    Reason about isolationPredict why a cross-site iframe can need a separate renderer process in Chrome.
  • 03
    Protect 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.

Definition

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.

A tiny process-list modelPop out in the code editor (opens in a new tab)JavaScript
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.

Major jobs in Chrome's overview
PartPlain jobWhy it is separate
Browser processOwns browser UI and privileged coordinationStarts navigation and coordinates other processes
Renderer processTurns a document into an interactive pageRuns page JavaScript, parsing, style, layout, and paint work
Network serviceFetches requests and responsesKeeps network work separate from page JavaScript
GPU processHandles graphics tasks in isolationReceives frames for display
Real-life analogyAn apartment building

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.

Playground: which process rows appear?
The process-list ruleJavaScript
const page = "shop.example";const iframe = "video.example";const siteIsolation = true; const renderers = siteIsolation && iframe !== page ? 2 : 1;console.log("renderers", renderers);
Model process list1 renderer
Browser processshared

tabs, address bar, privileged coordination

Network serviceshared

requests and responses

GPU processshared

submits graphics work

Renderer: shop.exampleshop.example

main document

Try it yourself

The model shows one renderer. Same-site frames can share it; turning Site Isolation off here is only a teaching contrast, not browser advice.

This is a deterministic process-list teaching model. Real browser process reuse and service layout vary by browser, device, and version.

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.

One ordinary page taskPop out in the code editor (opens in a new tab)JavaScript
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.

A tiny busy main-thread taskPop out in the code editor (opens in a new tab)JavaScript
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.

Step through a click waiting behind a long script
Step 0 of 8Ready
Your turn: follow the blue line

This is a replay of instrumented lesson code, not a browser engine debugger. It shows why one long main-thread task makes input wait.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
let finished = ""; function runNext() {  finished = tasks.shift() ?? "";  return finished;} console.log(runNext());console.log(runNext());
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

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.

A tiny chunk order modelPop out in the code editor (opens in a new tab)JavaScript
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.

Step through work split into smaller turns
Step 0 of 7Ready
Your turn: follow the blue line

This replay models splitting a large job into turns. It does not promise a particular browser scheduling API or timing.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
const completed = []; for (const task of chunks) {  completed.push(task);} console.log(completed.join(", "));
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

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.

A compositor-only teaching decisionPop out in the code editor (opens in a new tab)JavaScript
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.”

Where does this job belong?
  • 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
Try it yourself
0 of 6 correct

Sort each card by the part that most directly owns this job in the lesson's Chrome overview.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

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.
Easy words to keep separate
TermWhat it meansExample
ProcessSeparate program with private memoryA renderer for one site
ThreadA path of execution inside one processThe renderer main or compositor thread
Site isolationChrome process boundary for cross-site documentsA cross-site iframe renderer
CompositingCombines already-prepared layers into a frameScrolling a ready layer

Practice exercises

Exercise 1 · Warm-upCount model renderers

In the playground's cross-site, isolated case, how many renderer rows appear?

Starter codePop out in the code editor (opens in a new tab)JavaScript
console.log(2 + 1);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · Warm-upPredict the blocked work

    Type the first work item printed by this model.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const order = ["script", "click"];
    console.log(order.join(", "));

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeSpot a ready layer

      What does the ready-layer model print?

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      const mainThreadBusy = true;
      const layerIsReady = true;
      console.log(mainThreadBusy && layerIsReady ? "scroll" : "wait");

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeName the security boundary

        Your page embeds a document from a different site. What kind of document does Site Isolation place in a separate process?

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeKeep a dashboard responsive

          A dashboard recalculates thousands of rows after every keystroke. Name one safer response than one large synchronous loop.

          Answer, then press Check. Spacing and letter case don’t matter.

            Exercise 6 · ChallengeApply it to a real site

            A checkout button sometimes feels late. What should you inspect before guessing at a process or GPU fix?

            Answer, then press Check. Spacing and letter case don’t matter.

              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.

              Browser architecture quiz · 7 questionsScore: first tries count
              1. Question 1 of 7In Chrome, what normally owns page JavaScript inside a tab?

                Choose an answer to see the explanation.

              2. Question 2 of 7What does this print?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                const page = "shop.example";
                const iframe = "video.example";
                console.log(page === iframe ? 1 : 2);

                Choose an answer to see the explanation.

              3. Question 3 of 7What is Chrome Site Isolation for?

                Choose an answer to see the explanation.

              4. Question 4 of 7Why can a long script delay a click?

                Choose an answer to see the explanation.

              5. Question 5 of 7What does this model print?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                const busy = true;
                const ready = true;
                console.log(busy && ready ? "scroll" : "wait");

                Choose an answer to see the explanation.

              6. Question 6 of 7What do raster threads do in Chrome's rendering overview?

                Choose an answer to see the explanation.

              7. 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.

              CompleteFrontend Clear concepts. Working examples.