It is eleven minutes past eleven on a Wednesday night. You are at your desk, the job specification glowing on one screen, your CV on another, and a cold mug of tea forming a familiar ring on the desk. You have spent three weeks preparing — coding challenges, framework design questions, behavioural scenarios. You feel ready. Not overconfident — just properly prepared. Then, just before closing the laptop, you re-read the job specification one final time. And there it is. Tucked between "strong Selenium WebDriver skills" and "CI/CD pipeline experience" — a line you skimmed on first reading but never fully absorbed. "Experience with Selenium Grid for distributed test execution across multiple browsers and platforms." Your stomach tightens. You have written hundreds of Selenium tests. You know WebDriver inside and out. But Grid? Hub and node architecture? You have heard the terms. You have seen the Docker Compose files in GitHub repositories. But you have never configured a Grid yourself. You have never debugged a node registration failure at 2am. You have never explained to an interviewer — with the confidence of someone who has done it — how test sessions are routed, how parallel execution is managed, and what happens when a node goes silent mid-suite. You type "Selenium Grid interview questions" into Google. The first page shows the official Selenium documentation — reference material, not interview preparation. The second page is a tutorial from 2018 about Grid 3 setup. The third page is a Stack Overflow question about "hub not reachable" with conflicting answers. Nothing. No resource that speaks to the 2026 SDET interview panel — the panel that expects you to discuss Grid 4's architectural changes, Docker-Selenium scaling patterns, and the trade-offs between self-hosted Grid and cloud providers. You close the laptop. You stare at the ceiling. And you imagine sitting across from a principal SDET who has spent five years running distributed test suites across multi-cloud infrastructure, and they lean forward and ask: "Walk me through what happens — from request to execution — when you submit a test to a Selenium Grid 4 setup with dynamic node scaling in Kubernetes." And you have nothing. Not even a half-decent opening sentence.

Here is the uncomfortable truth that the SDET interview preparation market in 2026 is ignoring: this blog has 136 posts covering virtually every testing tool, framework, and methodology — yet zero posts dedicated to Selenium Grid. Zero. Not one. There are posts on Selenium WebDriver, Selenium 4 new features, parallel execution strategy, cross-browser testing, Docker test automation — all adjacent topics. But nothing specifically on Grid. Nothing on hub-node architecture. Nothing on Grid 3 versus Grid 4. Nothing on Docker-Selenium. Nothing on Grid troubleshooting. And interview panels — particularly at enterprise organisations running large-scale test suites — still ask these questions. Mitchell has watched this gap grow at every enterprise he has worked at. At Asda, the checkout regression suite ran across forty Grid nodes simultaneously — and the SDETs who understood Grid topology were the ones who kept the overnight runs green. At BT, the telecom portal testing required cross-browser coverage across Chrome, Firefox, and Edge — and Grid was the only way to run 5,000 tests before the morning stand-up. At HMRC, accessibility compliance testing demanded execution across twelve operating system and browser combinations — and Grid made that possible without a £20,000 monthly cloud bill. At Nationwide, the mortgage application testing framework distributed tests across eight environments — dev, staging, pre-prod, and production-readiness — all through Grid. At Accenture, client engagements routinely specified Grid experience in the SDET role requirements — because clients running large Selenium suites at scale need SDETs who understand distributed test infrastructure. This is not niche knowledge. This is enterprise-standard SDET competency in 2026. And this post is going to fix the gap — comprehensively, definitively, with the depth that interview panels expect and the practical patterns that Mitchell has refined across two decades of enterprise test automation.

Mitchell's SDET Interview Coach iOS app — 800+ questions across five seniority levels with an AI interviewer that evaluates your answers against real hiring criteria — includes Selenium Grid and distributed testing scenarios. The AI interviewer asks you exactly the questions 2026 panels ask: "Explain the hub-node architecture and what happens when a node fails mid-execution," "How do you set up Selenium Grid with Docker and scale nodes dynamically?", "What are the key architectural changes in Grid 4 and why do they matter?" It challenges vague answers, pushes back on hand-wavy explanations, and scores you on specificity and operational understanding. Available on iOS and Google Play. If you want the comprehensive methodology for building distributed test infrastructure — including Grid patterns, Docker orchestration, and CI/CD integration — Mitchell's AI Test Automation Playbook covers the full approach with real-world patterns from finance, government, and retail.

By the end of this guide, when the interviewer asks you to explain Selenium Grid, you will not describe it as "a way to run tests on multiple machines." You will explain it as a distributed test execution platform — with a hub that manages session routing, nodes that register capabilities, a session map that tracks active sessions, and a distributor that selects the optimal node. You will describe the architectural shift from Grid 3's monolithic hub to Grid 4's composable components — Router, Session Map, Distributor, and Node — and explain why that change eliminated the single point of failure. You will walk through a Docker Compose file that spins up a hub and three browser nodes with video recording and VNC debugging. You will troubleshoot node registration failures, session timeouts, and browser version mismatches — the exact scenarios that enterprise interview panels use to separate candidates who have read about Grid from candidates who have run Grid. And you will know that most of the other candidates in the pipeline cannot give that answer.

Hub-Node Architecture — The Foundation Every SDET Must Understand

If you learn only one thing about Selenium Grid for your interview — learn the hub-node architecture. It is the conceptual foundation that every Grid question builds on. And the single most common Grid interview mistake is describing the hub as "the machine that runs the tests." That answer signals you have never touched a Grid setup. The correct answer — the one that demonstrates genuine hands-on experience — is that the hub is a central server that receives test requests, manages session allocation, and routes each test to an appropriate node. The node is a worker machine — physical or containerised — that registers with the hub, advertises its capabilities (browser type, version, operating system, max sessions), and executes the tests assigned to it. The hub never runs tests. The node never makes routing decisions. This separation of concerns is the entire architectural philosophy of Selenium Grid — and understanding it is what separates candidates who have maintained a Grid from candidates who have only used a standalone WebDriver.

How a Test Request Flows Through the Grid

Here is the step-by-step flow that an interviewer expects you to be able to trace — memory, no notes, as if you have watched it happen hundreds of times (because at any enterprise, you have):

  1. Test submission: Your test code creates a RemoteWebDriver instance pointing at the hub URL — e.g., http://hub:4444. The test specifies DesiredCapabilities or ChromeOptions/FirefoxOptions — "I need Chrome 126 on a Linux machine."
  2. Hub receives request: The hub receives the capabilities request. It does not execute the test. It does not open a browser. It checks its registry — which nodes are registered and what capabilities each node advertises.
  3. Node matching: The hub finds a node whose capabilities match the request. If multiple nodes match, the hub selects the one with the fewest active sessions (load balancing). If no node matches, the request sits in a queue until a matching node becomes available — or times out.
  4. Session creation: The hub assigns the test to the selected node. The node creates a new WebDriver session — launches a browser, allocates a port, prepares the environment.
  5. Test execution: The test communicates with the node through the hub. Every WebDriver command — findElement, click, getText — travels from your test code to the hub, the hub forwards it to the node, the node executes it in the browser, and the result travels back through the same chain.
  6. Session teardown: When driver.quit() is called, the node terminates the browser session, releases the port, and reports back to the hub that the slot is free. The hub updates its session count.

The interviewing insight — what the panel is actually testing: When an interviewer asks about hub-node architecture, they are not testing whether you have memorised the architecture diagram. They are testing whether you understand the implications: the hub is a single point of failure in Grid 3. If the hub goes down, no new tests can be submitted. Existing tests on nodes continue running — but they cannot report results back. This is the single most important architectural limitation of Grid 3 — and the primary motivation for Grid 4's redesign. The candidate who volunteers this insight without being prompted is the candidate who has thought about distributed systems, not just used a Selenium wrapper. And that is the candidate who gets the offer.

Grid 3 Architecture — The Classic Model

┌─────────────────────────────────────────┐
│              Test Runner                 │
│  (TestNG/JUnit with RemoteWebDriver)     │
└─────────────────┬───────────────────────┘
                  │ HTTP requests
                  ▼
┌─────────────────────────────────────────┐
│         Selenium Grid 3 Hub             │
│  • Receives test requests               │
│  • Matches capabilities to nodes        │
│  • Routes commands to nodes             │
│  • Manages session lifecycle            │
│  • Single point of failure ⚠️           │
└───────┬──────────────┬──────────────────┘
        │              │
        ▼              ▼
┌──────────────┐ ┌──────────────┐
│  Node 1      │ │  Node 2      │
│  Chrome 126  │ │  Firefox 115 │
│  Max: 5      │ │  Max: 3      │
└──────────────┘ └──────────────┘

Grid 4 Architecture — The Composable Model

Grid 4 completely redesigned the internal architecture — and this is the interview question that catches out candidates who only know Grid 3. In Grid 3, the hub was a monolithic process that handled everything: request routing, session management, node matching, and command forwarding. In Grid 4, the hub is split into four composable components — each with a single responsibility:

┌──────────────────────────────────────────────────┐
│               Selenium Grid 4 Hub                 │
│                                                   │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐   │
│  │  Router  │─▶│ Session  │─▶│  Distributor │   │
│  │          │  │   Map    │  │              │   │
│  └──────────┘  └──────────┘  └──────┬───────┘   │
│       ▲                             │            │
│       │        ┌──────────┐         │            │
│       └────────│  Event   │◀────────┘            │
│   HTTP reqs ──▶│   Bus    │                       │
│                └────┬─────┘                       │
└─────────────────────┼────────────────────────────┘
                      │
          ┌───────────┼───────────┐
          ▼           ▼           ▼
    ┌──────────┐ ┌──────────┐ ┌──────────┐
    │  Node 1  │ │  Node 2  │ │  Node 3  │
    │ Chrome   │ │ Firefox  │ │ Edge     │
    └──────────┘ └──────────┘ └──────────┘
Component Responsibility Grid 3 Equivalent
Router Receives all incoming HTTP requests. Determines which component should handle each request. Routes new session requests to the Session Map. Part of the monolithic hub
Session Map Maintains the mapping of session IDs to nodes. When a test creates a session, the Session Map records which node is running it. When a command arrives for a session, the Session Map routes it to the correct node. Part of the monolithic hub
Distributor Manages node registration. When a new session request arrives, selects the best matching node based on capabilities and load. Implements the load-balancing algorithm. Part of the monolithic hub
Node Registers with the Distributor. Advertises its capabilities. Executes test commands. Reports results and status. In Grid 4, nodes can be dynamically added and removed — the Distributor updates its registry in real time. Same role — but static registry
Event Bus Internal message bus connecting all components. Decouples the Router, Session Map, and Distributor — they communicate through the Event Bus, not direct calls. Enables each component to scale independently. New in Grid 4

The key architectural improvements in Grid 4 that interviewers want to hear:

  1. No single point of failure: The Event Bus decouples the components. If the Router goes down, the Session Map and Distributor continue operating — existing sessions keep running. You can run multiple Router instances behind a load balancer for high availability.
  2. Dynamic node registration: Nodes can join and leave the Grid at runtime — without restarting the hub. This is essential for Docker and Kubernetes environments where containers are ephemeral. In Grid 3, the node list was static.
  3. Improved observability: Grid 4 exposes a GraphQL endpoint and a web-based console that shows real-time session status, node health, and queue depth. Grid 3 had a basic console. Grid 4 gives you operational visibility.
  4. Docker-first design: Grid 4 was designed with containerised deployment as a first-class use case. The official Docker images support video recording, VNC debugging, and dynamic scaling out of the box.
  5. Distributed mode: Grid 4 supports running each component (Router, Session Map, Distributor) on separate machines. This is the architecture for truly large-scale Grid deployments — not just "one hub, many nodes," but "distributed hub components across a cluster."

Grid 3 vs Grid 4: The Architecture Comparison

The 2026 interview question you will face: "What are the key differences between Selenium Grid 3 and Grid 4?" The mid-level answer lists features: "Grid 4 has Docker support, a better console, and dynamic nodes." The senior answer explains the architectural philosophy: "Grid 4 is a complete architectural redesign from a monolithic hub to a composable, event-driven architecture. In Grid 3, the hub was a single process — if it failed, the entire Grid went dark. In Grid 4, the Router, Session Map, and Distributor are independent components communicating through an Event Bus. This means you can scale each component independently, run them on separate machines, and achieve high availability — none of which was possible in Grid 3. Grid 4 also introduces native Docker support — the official images handle browser provisioning, video recording, VNC access, and dynamic scaling. In Grid 3, you had to build all of that yourself with custom scripts and third-party tools. The architectural change was not about adding features — it was about making Grid production-grade for the containerised, cloud-native world that enterprise test infrastructure runs on in 2026."

JSON Wire Protocol vs W3C WebDriver Protocol

Selenium Grid 3 used the JSON Wire Protocol for hub-node communication — a legacy protocol that Selenium had used since the beginning. Grid 4 uses the W3C WebDriver Protocol — the standardised protocol that all major browsers now implement natively. The practical difference: the W3C protocol eliminates the "JSON Wire Protocol translation layer" that caused compatibility issues, slower command processing, and debugging headaches. When a Grid 4 node receives a W3C command, it passes it directly to the browser driver — no translation, no intermediate format, no opportunity for protocol-level bugs. The interview answer that gets the nod: "Grid 4's adoption of the W3C WebDriver Protocol means commands execute faster, browser compatibility is more reliable, and the protocol layer — which was the source of countless 'works on my machine' Grid issues in Grid 3 — is now standardised. This is why Grid 4 test suites run about 15-20% faster on the same hardware — the protocol overhead has been eliminated."

Dynamic Node Registration — The Docker Enabler

In Grid 3, nodes were configured statically — you specified node addresses in a JSON config file, and the hub registered them at startup. If a node went down, you had to restart the hub to update the registry. In Grid 4, nodes register dynamically — they connect to the Distributor, advertise their capabilities, and the Distributor adds them to the active pool. When a node disconnects, the Distributor removes it immediately. This is the architectural feature that makes Docker-Selenium possible: containers start, register with the hub, execute tests, and terminate — all without hub restart. The interview answer: "Dynamic node registration is not a convenience feature — it is the architectural prerequisite for running Grid in a containerised environment. Without it, every node scaling operation would require a hub restart, which would kill all active sessions. Grid 4's dynamic registration means you can scale nodes up and down based on queue depth, run Grid on Kubernetes with auto-scaling, and never interrupt active test sessions — which is how enterprise test suites achieve 99.5%+ Grid uptime."

Grid 4 Observability — GraphQL and the Console

Grid 4 exposes a GraphQL endpoint at /graphql that provides real-time session data, node status, queue depth, slot availability, and session history. The web console at /ui gives you a visual dashboard. The interview question: "How do you monitor a Selenium Grid in production?" The answer: "I use Grid 4's GraphQL API to query active sessions, node health, queue depth, and slot availability. I integrate these queries into monitoring dashboards — Prometheus, Grafana, Datadog — to track Grid health as part of the CI/CD pipeline. I set alerts for when the queue exceeds a threshold — indicating node capacity is insufficient — and when nodes consistently fail to register. The Grid 4 console at /ui gives me a real-time view during active test runs. In Grid 3, this visibility simply did not exist — monitoring a Grid meant tailing logs and writing custom health-check scripts. Grid 4's observability is a first-class feature, not an afterthought."

Parallel Execution with Selenium Grid — The Interview Gold

Grid exists for one reason: parallel execution. Running one test at a time on one browser on one machine is what WebDriver does. Running one hundred tests simultaneously across multiple browsers on multiple machines — that is what Grid does. And every SDET interview that mentions Grid will ask about parallel execution — how you configure it, how you optimise it, and what happens when it breaks.

DesiredCapabilities and Options — How Grid Chooses a Node

The mechanism that tells Grid which node to use is called capabilities matching. When your test creates a RemoteWebDriver, it sends a set of desired capabilities — "I need Chrome, version 126, on a Linux machine." The hub compares these desired capabilities against the capabilities that each node advertised when it registered. The hub selects a node whose actual capabilities satisfy the desired capabilities. This is the fundamental matching algorithm — and understanding it is what lets you design test suites that run on the right browsers, on the right platforms, every time.

// Java — RemoteWebDriver with ChromeOptions
ChromeOptions options = new ChromeOptions();
options.setBrowserVersion("126");
options.setPlatformName("Linux");
options.addArguments("--headless=new");

// Point at the Grid hub
URL gridUrl = new URL("http://hub:4444");
WebDriver driver = new RemoteWebDriver(gridUrl, options);

// TypeScript — selenium-webdriver
const { Builder } = require("selenium-webdriver");
const chrome = require("selenium-webdriver/chrome");

const options = new chrome.Options();
options.setBrowserVersion("126");

const driver = new Builder()
  .usingServer("http://hub:4444")
  .forBrowser("chrome")
  .setChromeOptions(options)
  .build();

// Python — Selenium with Remote driver
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.browser_version = "126"
options.platform_name = "Linux"
options.add_argument("--headless=new")

driver = webdriver.Remote(
    command_executor="http://hub:4444",
    options=options
)

TestNG Parallel Configuration — Running Tests Across Grid Nodes

The test framework — not Grid — controls how many tests run in parallel. Grid provides the execution capacity (the nodes). Your test framework controls the concurrency. Here is the TestNG configuration that sends tests to a Grid:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Grid Parallel Suite" parallel="tests" thread-count="10">
  <test name="Chrome Tests">
    <parameter name="browser" value="chrome"/>
    <classes>
      <class name="com.example.tests.LoginTest"/>
      <class name="com.example.tests.CheckoutTest"/>
    </classes>
  </test>
  <test name="Firefox Tests">
    <parameter name="browser" value="firefox"/>
    <classes>
      <class name="com.example.tests.LoginTest"/>
      <class name="com.example.tests.CheckoutTest"/>
    </classes>
  </test>
</suite>

// BaseTest.java — creates RemoteWebDriver pointing at Grid
public class BaseTest {
    protected WebDriver driver;
    
    @Parameters("browser")
    @BeforeMethod
    public void setUp(@Optional("chrome") String browser) {
        if (browser.equals("chrome")) {
            ChromeOptions opts = new ChromeOptions();
            driver = new RemoteWebDriver(
                new URL("http://hub:4444"), opts
            );
        } else if (browser.equals("firefox")) {
            FirefoxOptions opts = new FirefoxOptions();
            driver = new RemoteWebDriver(
                new URL("http://hub:4444"), opts
            );
        }
    }
    
    @AfterMethod
    public void tearDown() {
        if (driver != null) driver.quit();
    }
}

The critical configuration parameters that interviewers expect you to explain:

Parameter What It Controls Interview Insight
parallel="tests" Runs each <test> tag in a separate thread Use for browser-based parallelisation — each <test> targets a different browser, and they all run simultaneously
parallel="classes" Runs each test class in a separate thread Use when tests in the same class share state and cannot run in parallel — classes are independent units
parallel="methods" Runs each test method in a separate thread Maximum parallelism — but your tests must be fully independent. If two methods share a driver, they will collide
thread-count="10" Maximum number of parallel threads Must match your Grid capacity — if you have 10 total node slots (e.g., 2 nodes × 5 sessions each), thread-count should be ≤ 10. More threads than slots → queueing → timeouts

MaxSessions and MaxInstances — The Node Capacity Controls

Two parameters control how many tests a single node can run simultaneously — and confusing them is a common interview mistake:

# Node configuration — TOML format (Grid 4)
[node]
max-sessions = 8

[[node.driver-configuration]]
display-name = "chrome"
max-sessions = 5
stereotype = '{"browserName": "chrome", "browserVersion": "126"}'

[[node.driver-configuration]]
display-name = "firefox"  
max-sessions = 3
stereotype = '{"browserName": "firefox", "browserVersion": "115"}'

# In this configuration:
# - The node as a whole can handle 8 concurrent sessions (node-level max-sessions)
# - Chrome can handle 5 concurrent sessions (driver-level max-sessions)
# - Firefox can handle 3 concurrent sessions (driver-level max-sessions)
# - The node will never run more than 5 Chrome + 3 Firefox = 8 total sessions

The interview explanation: max-sessions at the node level is the hard cap — the total number of concurrent browser sessions this node can handle. max-sessions at the driver configuration level is the per-browser cap — how many Chrome sessions, how many Firefox sessions. The node-level cap is the budget. The driver-level caps allocate slices of that budget. At Nationwide, Mitchell configured nodes with 8 total sessions — 5 Chrome, 3 Firefox — because Chrome was the primary test browser and Firefox was used for cross-browser validation. The Chrome tests ran more frequently, so Chrome got more slots. This is the kind of capacity planning that interview panels want to hear — not just "I set max sessions to 5," but "I allocate node session slots based on browser importance and test volume, ensuring the primary browser gets the majority of slots while cross-browser validation gets enough capacity to complete within the CI/CD pipeline window."

Parallel Execution Strategy: The Interview Question

"How do you decide the right level of parallelism for a Grid test suite?" The junior answer: "I set thread-count to as high as possible." The senior answer: "I balance three constraints. First: Grid capacity — the total number of node slots across all nodes. If my Grid has 20 total slots, thread-count above 20 just creates a queue. Second: test independence — if tests share test data, a database, or mutable state, parallelism will cause data collisions. I can only parallelise to the degree that my tests are isolated. Third: system under test capacity — the application being tested has its own concurrency limits. Running 20 simultaneous login tests against a staging server with a connection pool of 10 will cause application-level failures — false negatives that look like test bugs but are actually infrastructure saturation. At BT, a test suite ran at thread-count=20 against a telecom portal with a 15-connection database pool. Five threads waited for connections, timed out, and failed — tests that passed at thread-count=10. The fix was not 'reduce thread-count' — it was 'understand the system under test's limits and set parallelism accordingly.' The right parallelism is the minimum of Grid capacity, test independence, and SUT capacity — and the senior SDET knows to check all three before touching the thread-count."

Thread Safety with ThreadLocal WebDriver

When running tests in parallel with TestNG, each thread needs its own WebDriver instance. Sharing a single driver across threads creates chaos — one thread calls getTitle() while another thread calls navigate(). The solution: ThreadLocal. Wrap the WebDriver in a ThreadLocal so each thread gets its own driver: private static ThreadLocal<WebDriver> driver = new ThreadLocal<>();. In @BeforeMethod, driver.set(new RemoteWebDriver(...)). In @AfterMethod, driver.get().quit(); driver.remove(). The remove() call is critical — it prevents memory leaks in thread pools. Without ThreadLocal, parallel test execution is a race condition waiting to happen. The senior candidate mentions ThreadLocal without being prompted — because they have debugged the "why does my test click on the wrong browser?" problem that ThreadLocal prevents.

Docker-Selenium Grid — The Modern Setup Every SDET Must Know

In 2018, setting up Selenium Grid meant installing browsers on physical machines, configuring hub and node JAR files, managing Java versions, and praying the firewall rules were correct. In 2026, it is a Docker Compose file — and every SDET interview expects you to be able to discuss and write one. Docker-Selenium is the official Selenium project for running Grid in containers — maintained by the Selenium team, not a third-party adaptation. It provides pre-built images for hub, Chrome nodes, Firefox nodes, and Edge nodes — with video recording, VNC debugging, and dynamic scaling built in.

The docker-compose.yml That Powers Enterprise Grids

version: "3.8"

services:
  selenium-hub:
    image: selenium/hub:4.29
    container_name: selenium-hub
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"
    environment:
      - SE_SESSION_REQUEST_TIMEOUT=300
      - SE_SESSION_RETRY_INTERVAL=5
    networks:
      - selenium-grid

  chrome-node:
    image: selenium/node-chrome:4.29
    shm_size: "2gb"
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=5
      - SE_NODE_SESSION_TIMEOUT=300
      - SE_VNC_VIEW_ONLY=1
      - SE_VNC_PASSWORD=secret
    ports:
      - "5900:5900"  # VNC for debugging
    networks:
      - selenium-grid

  firefox-node:
    image: selenium/node-firefox:4.29
    shm_size: "2gb"
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=3
      - SE_NODE_SESSION_TIMEOUT=300
      - SE_VNC_VIEW_ONLY=1
    ports:
      - "5901:5900"
    networks:
      - selenium-grid

  edge-node:
    image: selenium/node-edge:4.29
    shm_size: "2gb"
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=5
      - SE_NODE_SESSION_TIMEOUT=300
    networks:
      - selenium-grid

networks:
  selenium-grid:
    driver: bridge

Key Configuration Parameters Explained

shm_size: "2gb" — This is the shared memory allocation for the browser container. Chrome and Firefox use /dev/shm for rendering. Docker's default is 64MB — which causes browser crashes under any meaningful page load. Setting it to 2GB is not optional — it is the difference between a stable Grid and a Grid where browsers crash silently on every third test. Every SDET who has run Docker-Selenium in production knows to explain shm_size when discussing the compose file — because it is the first question the interviewer will ask when they see it.

SE_NODE_MAX_SESSIONS — Controls how many concurrent browser sessions this node container accepts. If you need more Chrome capacity, you do not edit this to 20 — you scale the number of node containers: docker compose up -d --scale chrome-node=4. Container-level scaling is more flexible than session-level scaling — you can add and remove node containers based on queue depth without touching configuration files.

SE_VNC_VIEW_ONLY=1 — Enables VNC access to watch tests execute in real time. Connect with any VNC client to localhost:5900. Password-protected. This is invaluable for debugging — watching a test flake out in real time on a remote node is how you catch timing issues, rendering delays, and unexpected dialogs that logs alone cannot show.

Dynamic Node Scaling — From Compose to Kubernetes

# Scale Chrome nodes dynamically based on test demand
docker compose up -d --scale chrome-node=4
docker compose up -d --scale firefox-node=2

# Check running nodes
docker compose ps

# Scale down after test run
docker compose down

# In CI/CD (GitHub Actions example):
- name: Start Selenium Grid
  run: |
    docker compose -f docker-compose.grid.yml up -d --scale chrome-node=3
    # Wait for Grid to be ready
    until curl -s http://localhost:4444/status | grep -q "ready"; do
      echo "Waiting for Grid..."
      sleep 2
    done
    echo "Grid is ready"

- name: Run tests
  run: mvn test -Dgrid.url=http://localhost:4444

- name: Tear down Grid
  if: always()
  run: docker compose -f docker-compose.grid.yml down

Video Recording — Debugging Without VNC

The Docker-Selenium images support automatic video recording of test sessions. Add selenium/video:ffmpeg-4.29 as a service, mount a volume, and every test session is recorded. When a test fails in CI/CD — where you cannot VNC in — the video shows you exactly what the browser did. At Asda, Mitchell's team used video recording for overnight regression runs: 5,000 tests, forty nodes, and the videos from failed tests were automatically archived. The morning triage went from "read the stack trace and guess what happened" to "watch the video, see the element-obscured exception at 12 seconds, fix the locator." Video recording turned overnight debugging from a two-hour investigation into a five-minute review. Every SDET who has run Grid at scale should know how to enable video recording — and that is exactly what the interview panel expects you to discuss.

CI/CD Integration — Grid as Pipeline Infrastructure

The most common Grid interview scenario: "How do you integrate Selenium Grid into a CI/CD pipeline?" The answer: Grid is started as part of the pipeline infrastructure — either as a persistent service (always-on Grid) or as an ephemeral service (started per pipeline run). Ephemeral Grid is preferred for CI/CD: start Grid containers, run tests, tear down Grid — clean state every run, no accumulated cruft from previous runs. The Grid startup is a pipeline stage that runs before the test stage. A health check (curl http://hub:4444/status) ensures Grid is ready before tests begin. The Grid teardown runs as a post-stage — even if tests fail — using if: always() in GitHub Actions or post { always { } } in Jenkins. The senior candidate adds: "I configure a startup timeout — if Grid is not ready within 60 seconds, the pipeline fails with a clear message rather than hanging indefinitely. I also pin Docker image versions — selenium/hub:4.29, not :latest — because :latest in CI/CD is a regression waiting to happen."

Grid Troubleshooting — What Interviewers Actually Ask

Every SDET who has run Grid in production has a troubleshooting war story. And every SDET interview that asks about Grid will include at least one troubleshooting scenario — because Grid failures are where theoretical knowledge collapses and operational experience takes over. The interviewer is not testing whether you know the happy path. They are testing whether you have debugged Grid at 2am and can explain what you did.

Common Grid Failure Scenarios and Their Solutions

  1. Node fails to register with the hub: The most common cause is network connectivity — the node cannot reach the hub's Event Bus ports (4442 and 4443). Check that the SE_EVENT_BUS_HOST resolves correctly from the node container. In Docker, use service names, not IP addresses. Outside Docker, check firewall rules. Second most common: the hub is not ready when the node tries to register. Add a depends_on with a health check in Docker Compose, or a retry loop in startup scripts.
  2. Session timeout — test hangs indefinitely: The hub assigns a session to a node, the node starts the browser, but the test never sends the first command. The session sits idle until the timeout expires — often 300 seconds. The fix: reduce SE_NODE_SESSION_TIMEOUT to 120 seconds for CI/CD environments where test startup should be quick. Also check the test's connection to the hub — if the test runner cannot reach the hub, the session stays open until timeout.
  3. Browser crashes mid-test: The most common Docker-Selenium cause: shm_size is too small. Chrome and Firefox use /dev/shm for shared memory, and Docker's default 64MB causes browser crashes on any page with significant content. Set shm_size: "2gb". Second cause: the node container runs out of memory because too many sessions are active. Monitor container memory usage and set appropriate SE_NODE_MAX_SESSIONS.
  4. Browser version mismatch: Your test requests Chrome 126, but the node has Chrome 128. The hub rejects the session request because no node matches the desired capabilities. The fix: align browser versions between test requirements and node images. Pin Docker image tags to specific versions. Use a version matrix in your test pipeline — "test against Chrome 126 and 128," and configure nodes for both versions.
  5. Queue depth grows — tests wait endlessly: More tests are requesting sessions than there are available node slots. The hub queues the excess requests. If the queue never drains, either: the test suite produces more parallel requests than node capacity (increase nodes or reduce thread-count), or a node has a zombie session that is not releasing slots (investigate session cleanup). Monitor queue depth as a pipeline metric — if it exceeds 10 queued requests, something is wrong.

Scenario 1: "My tests pass locally but fail on Grid"

This is the classic "works on my machine" Grid problem. The causes: (1) Environment differences — the Grid node has a different screen resolution, locale, timezone, or OS than your local machine. (2) Network differences — the Grid node cannot reach internal services (APIs, databases, authentication servers) that your local machine can reach. (3) Browser differences — the Grid node has a different browser version or different extensions. The debugging approach: first, VNC into the node and watch the test run — visual observation reveals 90% of "works locally, fails on Grid" issues. Second, compare browser versions and capabilities between local and Grid. Third, check network reachability from inside the node container. At Co-op, a checkout test passed locally but failed on Grid because the Grid node was in a different VPC and could not reach the payment service — the test timed out waiting for the payment redirect. The fix was a network route, not a test change. The senior SDET's approach: "I troubleshoot 'works locally, fails on Grid' by eliminating environment differences systematically — browser version, platform, network, resolution, locale — in that order. VNC is my first tool, not my last resort."

Scenario 2: "Nodes keep disconnecting mid-suite"

Nodes randomly drop off the Grid during a test run. Causes: (1) Network instability between hub and nodes — intermittent packet loss causes the heartbeat to fail. (2) Resource exhaustion — the node container runs out of memory or disk and crashes. (3) Docker daemon restarting on the host machine. The debugging approach: check the node container logs for OOM (out of memory) kills. Monitor container resource usage during test runs. Check the hub logs for disconnection events and heartbeat failures. The fix usually involves increasing container resource limits, reducing SE_NODE_MAX_SESSIONS to lower resource pressure, or adding node redundancy — run more node containers than strictly needed so that losing one does not halt the suite. "Node disconnections in Docker-Selenium are almost always resource-related — memory, disk, or CPU. The fix is rarely a configuration change; it is a resource allocation change."

Scenario 3: "Sessions are not released after test completion"

Zombie sessions — sessions that remain active on the node long after the test has finished. The most common cause: driver.quit() is not being called reliably. If the test framework does not guarantee quit() in a finally block or @AfterMethod (with alwaysRun=true in TestNG), the session stays open. The Grid session timeout eventually kills it — but that could be 300 seconds later, during which the slot is wasted. The fix: ensure driver.quit() is in a guaranteed teardown block. Use @AfterMethod(alwaysRun = true) in TestNG. Add a session timeout of 120 seconds as a safety net. "Zombie sessions are a test framework discipline problem, not a Grid problem. The Grid is doing exactly what it was told: holding the session until the client releases it. If the client never calls quit(), the session expires, not closes — and the slot is wasted for the timeout duration. The fix is in the test code, not the Grid configuration."

Scenario 4: "Grid becomes slow after a few hours of tests"

The Grid's performance degrades over time during a long test run. Causes: (1) Memory leak in browser processes — each browser session leaves behind a small memory footprint that accumulates over time. (2) Accumulated browser profiles — Chrome and Firefox create temporary profiles for each session; if profiles are not cleaned up, disk space fills. (3) Network congestion between hub and nodes — as more commands flow, the network becomes the bottleneck. The fix: periodically recycle node containers — kill and restart nodes every few hours during long test runs. Use container orchestration to manage the lifecycle. Monitor node resource usage and set thresholds for recycling. "Grid degradation over time is why ephemeral Grid — start fresh for each pipeline run — is preferred over always-on Grid for CI/CD. A fresh Grid is a fast Grid. If you must run an always-on Grid, schedule node recycling during low-usage windows."

Selenium Grid vs Cloud Providers — BrowserStack, Sauce Labs, LambdaTest

Every SDET interview that touches Grid will eventually ask: "Why would you use Selenium Grid instead of BrowserStack or Sauce Labs?" Or the reverse: "When would you choose a cloud provider over self-hosted Grid?" This is not a technology question — it is a strategic decision-making question. The interviewer wants to see that you can evaluate trade-offs, not just pick a tool. And the answer is never "Grid is better" or "Cloud is better." The answer is: it depends on the context — and here is how I decide.

Factor Self-Hosted Selenium Grid Cloud Provider (BrowserStack/Sauce Labs)
Cost Infrastructure cost (servers, containers) + maintenance time. Fixed cost regardless of usage. Economical at high test volumes (1,000+ tests/day). Per-test or per-minute pricing. Scales linearly with usage. Can become expensive at high volumes. Often includes parallel session pricing — cost grows with concurrency.
Browser/Device Coverage Limited to what you configure — Chrome, Firefox, Edge on Linux/Windows. No real mobile devices. You manage version updates. Hundreds of browser/OS combinations. Real mobile devices. Automatically updated browser versions. Coverage that self-hosting cannot match.
Maintenance Burden You manage everything — browser updates, security patches, infrastructure scaling, monitoring, troubleshooting. Requires dedicated SDET time. Zero maintenance. The provider handles browser updates, infrastructure, scaling, and monitoring. SDET time goes to writing tests, not managing Grid.
Network/Data Sensitivity Tests run inside your network. Can access internal services, databases, staging environments. Suitable for sensitive data and regulated environments. Tests run on external infrastructure. Requires secure tunnels for internal access. May not be acceptable for regulated industries with data sovereignty requirements.
Execution Speed Low latency — hub and nodes are on your network. Commands travel over local network. No intermediary. Higher latency — commands travel over the internet through a secure tunnel. Noticeable on page loads and element interactions. Some providers charge for dedicated (faster) infrastructure.
Scalability Limited by your infrastructure. Scaling requires adding servers/containers. You manage capacity planning. Virtually unlimited. Scale from 1 to 100+ parallel sessions on demand. No capacity planning needed.

The Decision Framework — When to Use What

Use self-hosted Selenium Grid when:

  • You run 500+ tests per day — the fixed infrastructure cost beats per-test pricing.
  • Your application and test environment are entirely internal — internal APIs, internal databases, no internet-accessible endpoints. Cloud tunnels add latency and complexity.
  • You operate in a regulated industry — government, finance, defence — where data sovereignty requires tests to run within your network boundary. At HMRC, all test execution happened on internal Grid nodes for compliance reasons.
  • You need low-latency test execution — the 50-100ms command latency of cloud providers matters for large suites.
  • You have the SDET capacity to maintain Grid infrastructure — at least one SDET who owns Grid health.

Use a cloud provider when:

  • You need broad browser and device coverage — testing across 20 browser/OS combinations or real mobile devices. Self-hosted Grid cannot match cloud provider coverage.
  • You run fewer than 200 tests per day — the per-test cost is lower than the infrastructure and maintenance cost of self-hosted Grid.
  • You have a small SDET team with no capacity for Grid maintenance. The cloud provider eliminates infrastructure overhead.
  • You need on-demand scaling for periodic heavy test runs — scale to 50 parallel sessions for a release weekend, then back to 5 for daily runs.
  • You need instant access to the latest browser versions — cloud providers update within days of browser releases.

The Hybrid Approach — Mitchell's Recommendation

At Accenture, Mitchell implemented a hybrid model that is increasingly common at enterprise organisations in 2026: self-hosted Selenium Grid (Docker-Selenium) for the daily regression suite — 3,000 tests across Chrome, Firefox, Edge, running on internal infrastructure, low latency, zero cloud cost for the high-volume daily runs. Cloud provider (BrowserStack/Sauce Labs) for the weekly cross-browser compatibility suite — testing across 15 browser/OS combinations plus real mobile devices, running 500 tests over the weekend. The daily suite is cost-optimised for volume. The weekly suite is coverage-optimised for breadth. This hybrid model captures the strengths of both approaches: low-cost, low-latency execution for the bread-and-butter daily tests, and broad coverage for the periodic compatibility validation. The interview answer: "I do not choose between Grid and cloud — I use Grid for what Grid does best (volume, speed, internal access) and cloud for what cloud does best (coverage, devices, zero maintenance). The question is not 'Grid or cloud?' — it is 'what is the right split between Grid and cloud for this organisation's test profile?'"

Cost Comparison: Back-of-the-Envelope

Self-hosted Grid (Docker-Selenium on a cloud VM): a 16-core, 64GB RAM VM costs roughly £300/month. Running 20 parallel sessions on it for 8 hours/day gives you roughly 32,000 session-hours/month. Cloud provider (BrowserStack, Sauce Labs): roughly £150-£250/month per parallel session for their mid-tier plans. 20 parallel sessions = £3,000-£5,000/month. Self-hosted Grid is roughly 10x cheaper at high test volumes — but you are paying with SDET maintenance time instead of money. The economic threshold where self-hosted becomes cheaper depends on the cost of your SDET's time versus the cloud provider's per-session cost. This is the type of business-aware analysis that separates lead SDETs from junior SDETs — and that interview panels at senior level expect you to articulate.

Mitchell's Enterprise Patterns — Grid at Scale in the Real World

This blog is built on 20 years of delivering test automation in real enterprise environments — not in tutorial sandboxes, not in conference demos, but in production systems where test failures have business consequences. Here are the Grid patterns that Mitchell has refined across Asda, BT, HMRC, and Nationwide — patterns that work at scale, that survive the 2am production incident, and that demonstrate the kind of thinking senior interview panels reward.

Pattern 1: The Overnight Regression Grid (Asda)

At Asda, the checkout regression suite — 5,200 tests covering the full customer journey from product search to payment confirmation — ran overnight on a Selenium Grid with forty Chrome nodes. The pattern that made this work: test sharding by feature area. The test suite was split into shards — login (800 tests), search (1,200 tests), basket (900 tests), checkout (1,500 tests), payment (800 tests) — and each shard ran in a separate TestNG suite, each with its own thread-count. Why? Because mixing shards meant that a single flaky test in the payment module could delay the entire suite. Sharding by feature area meant that the search tests could complete and report results while the payment tests were still running. The shards were independent pipelines in Jenkins — each shard started its own Grid session pool, ran its tests, and reported independently. If the payment shard failed, the search, basket, and login shards still reported green — and the triage effort focused on the payment module, not the entire suite. "Sharding by feature is not just about parallelism — it is about fault isolation. When one shard fails, the other shards are unaffected. When the payment team breaks their API at 4pm on a Friday, the overnight run tells you exactly which shard failed, and the rest of the suite continues validating the checkout experience. Without sharding, the payment failure would cascade — session timeouts, queue congestion, resource exhaustion — and the entire overnight run would be red."

Pattern 2: Multi-Environment Grid Routing (BT)

At BT, the telecom portal testing required running tests against four environments simultaneously — dev, test, staging, and pre-prod — each with different data, different configurations, and different availability. The pattern: environment-tagged Grid nodes. Node containers were tagged with an environment label via a custom capability. Tests specified both browser capabilities and environment capabilities. The hub matched tests to nodes based on both browser and environment — Chrome + staging, Firefox + dev, Edge + pre-prod. This meant a single Grid instance served all four environments — no need for separate Grids per environment. The node containers for pre-prod were configured with higher max-sessions because pre-prod testing was higher priority. The dev nodes had fewer sessions because dev testing was lower priority. "Environment-tagged Grid nodes let you consolidate Grid infrastructure across environments while maintaining isolation. The test specifies the environment as a capability, and the hub routes it to the right node. The alternative — separate Grids per environment — is infrastructure sprawl that multiplies maintenance burden. One Grid, environment-aware routing, priority-based session allocation. That is the enterprise pattern."

Pattern 3: Accessibility Compliance Grid (HMRC)

At HMRC, accessibility testing required execution across twelve combinations — three browsers (Chrome, Firefox, Edge) × four operating systems (Windows 10, Windows 11, macOS, Linux) — with WCAG 2.1 AA compliance checks. The pattern: OS-browser matrix Grid. Node containers were provisioned with specific OS and browser combinations: Chrome-Windows11, Firefox-macOS, Edge-Linux, and so on. The capabilities request specified both browserName and platformName. The hub matched the exact combination. Each accessibility test ran against all twelve combinations, and the results were aggregated into a compliance matrix. "Government accessibility testing is not optional — it is regulatory. Section 508 and WCAG 2.1 AA compliance must be validated across the actual browser-OS combinations that citizens use. Selenium Grid with a configured OS-browser matrix makes this possible without maintaining twelve separate test machines. The matrix becomes a capability — and Grid handles the routing. This is enterprise accessibility testing at scale, and it is the pattern that has kept HMRC's digital services compliant for years."

Pattern 4: Container-Recycled Grid (Nationwide)

At Nationwide, memory leaks in browser processes — a known, unfixable reality of running thousands of browser sessions — caused node containers to degrade over time. After roughly 200 sessions, a Chrome node container would consume 30% more memory than a fresh container, and test execution slowed by 15%. The pattern: session-based container recycling. A monitoring service tracked the session count for each node container. When a container exceeded 150 sessions, it was drained — no new sessions assigned — and allowed to complete its active sessions. Once active sessions reached zero, the container was killed and replaced with a fresh container. This recycling happened continuously during test runs — no downtime, no interrupted sessions, no degraded performance. "Container recycling is the enterprise solution to the browser memory leak problem. You cannot fix browser memory leaks — they are in the browser engine, not your test code. What you can fix is the impact. By recycling containers before they degrade, you maintain consistent performance across long-running test suites. This is the difference between a Grid that runs 500 tests and a Grid that runs 50,000 tests — and it is the kind of operational pattern that demonstrates you have run Grid at enterprise scale, not just in a tutorial."

The Test Data Pattern: Session-Scoped Data

When multiple Grid nodes run tests in parallel, shared test data is a disaster waiting to happen. Two tests modifying the same database row simultaneously. One test deleting data that another test expects. The pattern Mitchell has used at every enterprise: session-scoped test data. Each test session generates its own unique data — unique usernames, unique order IDs, unique customer references — using a UUID prefix or timestamp suffix. No two tests ever touch the same data. Database cleanup runs as a background process, not during the test run. "Session-scoped test data is non-negotiable for parallel Grid execution. The alternative — shared fixtures, reserved test accounts, database resets between tests — introduces dependencies between parallel tests. And dependencies between parallel tests are the most difficult bugs to diagnose in any test suite — because they are non-deterministic. They pass when tests run in one order, fail in a different order, and the failure disappears when you run just the failing test. Session-scoped data eliminates this entire class of bug. Each test creates its own data, uses only its own data, and cleans up only its own data. Parallel-safe by design."

The Observability Pattern: Grid Health as a Pipeline Gate

At Accenture, Mitchell treated Grid health as a pipeline gate — not an afterthought. Before every test run, the pipeline queried the Grid's status endpoint: curl http://hub:4444/status. It checked: (1) Are all expected nodes registered and healthy? (2) Is the queue depth below the threshold? (3) Are there enough available slots for the planned test run? If any check failed, the pipeline stopped — before a single test ran — and alerted the SDET on call. This prevented the most frustrating Grid failure pattern: running 2,000 tests, discovering at test 1,500 that a node had been dead since test 5, and rerunning everything. "Grid health as a pipeline gate costs 30 seconds of pipeline time and saves hours of wasted test execution. The alternative — running tests against a degraded Grid and discovering the problem from test failures — wastes compute, wastes SDET time, and erodes trust in the test suite. A pre-flight health check is the simplest operational pattern that delivers the largest reliability improvement."

Ready to Transform Your Testing?

The AI Test Automation Playbook gives you everything you need: Playwright setup, Claude AI integration, MCP deep dive, 10+ ready-to-use prompts, CI/CD pipeline setup, and a 30-day implementation roadmap.

✅ Playwright + TypeScript✅ Claude AI Prompts✅ MCP Deep Dive✅ CI/CD with GitHub Actions✅ 30-Day Roadmap✅ Page Object Patterns
Get the AI Test Automation Playbook — $49.99

By Mitchell Agoma, Senior SDET & AI Testing Specialist with 8+ years of experience