PRACTICAL GUIDE / Selenium Grid GraphQL dashboard
Build a Selenium Grid Capacity Dashboard with GraphQL
Build a Selenium Grid GraphQL dashboard for node health, sessions, queue depth, compatible slot capacity, stale-data handling, and actionable alerts.
In this guide11 sections
- Start with the supported Grid schema
- Query Grid and Node capacity together
- Poll with transport and GraphQL validation
- Calculate concurrency without confusing slots
- Break capacity down by compatible stereotype
- Design panels around operational decisions
- Alert on sustained, fresh conditions
- Protect the GraphQL surface and its data
- Diagnose a broken dashboard by layer
- Capacity dashboard checklist
- Make the dashboard explain the queue
What you will learn
- Start with the supported Grid schema
- Query Grid and Node capacity together
- Poll with transport and GraphQL validation
- Calculate concurrency without confusing slots
A Selenium Grid GraphQL dashboard should answer three operational questions: can Nodes accept work, is compatible capacity available, and are new-session requests waiting? The endpoint already exposes Grid, Node, session, slot, stereotype, status, and queue fields. A focused poller can turn that model into evidence without scraping the Grid UI or querying every component independently.
Capacity is not one number. Configured slots describe browser choices, maxSession limits concurrent execution, sessionCount reports current use, Node status controls eligibility, and queue depth shows demand that has not yet been assigned. A useful dashboard preserves those distinctions instead of compressing them into a misleading green percentage.
Start with the supported Grid schema
The official Selenium GraphQL guide documents the /graphql endpoint and fields under grid, nodesInfo, sessionsInfo, and session(id: ...). Query only fields that drive a panel, calculation, alert, or diagnostic link.
Animated field map
Grid Capacity Dashboard Pipeline
Poll the GraphQL endpoint, validate its model, calculate bounded capacity, and alert only from fresh compatible-state evidence.
01 / dashboard poller
Dashboard Poller
Send a bounded authenticated request and timestamp the observation.
02 / graphql endpoint
Grid GraphQL Endpoint
Return selected Grid, Node, session, queue, and stereotype fields.
03 / slot model
Node and Slot Model
Validate statuses, concurrency limits, slot counts, and capabilities.
04 / utilization
Utilization Calculation
Separate active sessions, concurrency headroom, and compatible slots.
05 / capacity alert
Capacity Alert
Evaluate sustained fresh conditions with diagnostic dimensions.
Treat the schema as an external contract. Test the dashboard query against the exact Grid release in staging. GraphQL lets a client select fields, but requesting a field absent from that deployed schema returns a query error rather than silently omitting it.
Query Grid and Node capacity together
One request can retrieve the global summary and enough Node detail to explain it. The query below avoids complete session payloads and operating-system details because the main capacity panels do not need them.
query GridCapacity {
grid {
uri
version
nodeCount
totalSlots
maxSession
sessionCount
sessionQueueSize
}
nodesInfo {
nodes {
id
uri
status
maxSession
slotCount
sessionCount
stereotypes
}
}
}Node status is an enum with states including UP, DRAINING, and UNAVAILABLE. Do not collapse those into an online boolean. A draining Node may continue existing sessions while correctly refusing new work, and an unavailable Node's configured slots should not count as immediately usable capacity.
Use a separate detail query when an operator opens a session or Node view. Fetching every capability and session field on every dashboard tick increases payload size and exposes more potentially sensitive metadata without improving the top-level signal.
Poll with transport and GraphQL validation
Set a request timeout shorter than the poll interval, allow only one in-flight poll, and retain the last good sample when a fetch fails. Mark it stale rather than replacing it with zeros. Zero sessions from a failed parser looks like a healthy idle Grid and can suppress the alert that matters.
type GraphQLError = { message: string };
type CapacityData = {
grid: {
nodeCount: number;
totalSlots: number;
maxSession: number;
sessionCount: number;
sessionQueueSize: number;
};
nodesInfo: {
nodes: Array<{
id: string;
uri: string;
status: "UP" | "DRAINING" | "UNAVAILABLE";
maxSession: number;
slotCount: number;
sessionCount: number;
stereotypes: unknown;
}>;
};
};
export async function fetchCapacity(
endpoint: string,
signal: AbortSignal,
): Promise<{ data: CapacityData; observedAt: string }> {
const response = await fetch(endpoint, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ query: CAPACITY_QUERY }),
signal,
});
if (!response.ok) throw new Error(`GraphQL HTTP ${response.status}`);
const payload = (await response.json()) as {
data?: CapacityData;
errors?: GraphQLError[];
};
if (payload.errors?.length || !payload.data) {
throw new Error(payload.errors?.map((e) => e.message).join("; ") ?? "Missing data");
}
return { data: payload.data, observedAt: new Date().toISOString() };
}CAPACITY_QUERY should be the version-controlled GraphQL document shown above. Validate numeric fields as finite, non-negative values before calculating. A syntactically valid JSON object with an unexpected schema is not a healthy sample.
Calculate concurrency without confusing slots
At Grid level, current concurrency is sessionCount. The reported maxSession is the direct ceiling for the aggregate utilization calculation. Guard division by zero and present both numerator and denominator:
export function utilization(sessionCount: number, maxSession: number) {
const used = Math.max(0, sessionCount);
const limit = Math.max(0, maxSession);
return {
used,
limit,
available: Math.max(0, limit - used),
ratio: limit === 0 ? null : Math.min(1, used / limit),
};
}Display totalSlots separately as configured slot inventory. A Node can expose several browser stereotypes while a lower Node-wide maximum restricts simultaneous sessions. Using total slots as the denominator can make a saturated Grid appear underused.
At Node level, calculate sessionCount / maxSession, then annotate status and slot count. Exclude unavailable Nodes from ready capacity. Treat draining capacity as currently occupied or retiring, not available for assignment.
Break capacity down by compatible stereotype
Global headroom cannot answer whether a Firefox-on-Linux request can start. Parse the documented stereotype representation defensively, normalize browser name, platform, and the approved scheduling capabilities, and group slots by that key. Keep the raw value for diagnostics when parsing fails.
For each group, show configured slots on UP Nodes, active matching sessions where the response model provides enough evidence, and Node-wide headroom. The usable value is bounded by both compatible free slots and the remaining Node maximum. Do not sum every stereotype independently when several share one Node concurrency cap.
Queue capabilities are the demand side of this calculation. Fetch sessionsInfo.sessionQueueRequests only for a protected diagnostic view or a targeted classifier, because request payloads may include names, URLs, provider options, and other sensitive values. Redact before storage.
Design panels around operational decisions
The first row should show fresh-sample time, Grid status, active sessions, concurrency limit, queue size, and unavailable or draining Node counts. A second view can group browser and platform capacity. A Node table should include status, active over maximum, slot count, URI or stable label, and last successful poll.
Avoid a decorative wall of gauges. Operators need to scan mismatches: queue growing while one browser group is full, a Node draining unexpectedly, advertised slots disappearing after a rollout, or session count staying high after jobs end.
Link a Node or session to its corresponding logs and traces using stable identifiers. The dashboard should lead into evidence, not reproduce every diagnostic system in one page.
Alert on sustained, fresh conditions
Choose thresholds from service objectives and measured session startup behavior rather than copying fixed numbers. Useful alert conditions include a queue that remains nonzero beyond the expected startup window, no UP Nodes for a required stereotype, sustained concurrency saturation, an unexpected fall in configured capacity, and samples stale beyond the poll policy.
Require multiple fresh observations or an explicit duration so one rollout tick does not page the team. Include Grid identity, affected stereotype, queue size, active and maximum sessions, Node statuses, first observed time, and dashboard link in the alert.
Do not claim a scheduler failure merely because global available capacity is positive. First prove that a queued request has a compatible free slot on an eligible Node. A dashboard that preserves this nuance shortens incident triage substantially.
Protect the GraphQL surface and its data
Expose GraphQL through the same authenticated, HTTPS-protected Router boundary as the rest of Grid. Do not publish it directly to an untrusted network. Apply a short request timeout and rate limits at the dashboard service so a broken poll loop cannot become control-plane load.
Node URIs, session metadata, capabilities, and queue requests can reveal internal topology or test data. Fetch the minimum schema, limit dashboard access, and define retention for derived metrics separately from raw responses. Never place Grid credentials in browser-delivered JavaScript; poll from a trusted backend.
Cache only briefly enough to absorb multiple dashboard viewers. Operational capacity must remain fresh, and each sample should carry both observation time and Grid identity to prevent cross-environment mixing.
Diagnose a broken dashboard by layer
An HTTP 404 usually points to the wrong Router, sub-path, or proxy route. A 401 or 403 is authentication or authorization. HTTP success with GraphQL errors indicates query-schema mismatch or invalid field selection. Valid data with impossible calculations indicates response validation or arithmetic defects.
If Node count drops, compare Grid deployment and registration logs before changing the dashboard. If counts disagree with the UI, make sure both are querying the same Grid endpoint and time. If polls overlap, abort or skip the older request; accepting a late response can move the dashboard backward in time.
When stereotype parsing fails, display that fact and retain the sanitized raw field. Silently assigning an unknown stereotype to "other" can hide the exact capacity a release removed.
Capacity dashboard checklist
- Query only fields tied to panels, calculations, alerts, or drill-down.
- Test the GraphQL document against the promoted Grid release.
- Validate HTTP status, JSON, GraphQL errors, and required data.
- Allow only one bounded poll in flight and timestamp every sample.
- Keep the last good sample visible but clearly stale on failure.
- Use
maxSession, not total slot count, for concurrency utilization. - Preserve Node statuses instead of reducing them to online or offline.
- Break demand and capacity down by compatible stereotypes.
- Avoid double-counting stereotypes that share a Node-wide limit.
- Protect GraphQL with server-side authentication, HTTPS, and rate controls.
- Alert only on sustained conditions from fresh samples.
Make the dashboard explain the queue
The dashboard is complete when it can show not just that work is waiting, but whether the missing resource is concurrency, a compatible stereotype, an eligible Node, or fresh data. Query a narrow supported schema, validate every sample, and keep configured slots separate from executable capacity. That model gives operators a trustworthy starting point for scaling and failure analysis.
// LIVE COURSE / THE TESTING ACADEMY
Playwright Automation Mastery
Go beyond Selenium. Master Playwright with JS/TS in 90 days.
From the instructor behind this guide.
Playwright jobs are growing 8x faster than Selenium. 90 days / 75+ live hrs / Tue-Thu-Sat 7 AM IST.
PRIMARY REFERENCES
Verify the details at the source
QABattle guides are practical explanations. Product behavior, standards, and APIs can change, so use these primary references for the canonical details.
- 01Selenium documentation
Selenium Project
Canonical WebDriver, Grid, waits, element, and browser automation guidance.
- 02WebDriver standard
W3C
The browser automation protocol specification behind WebDriver implementations.
- 03GraphQL specification
GraphQL Foundation
The normative schema, operation, validation, and execution specification.
FAQ / QUICK ANSWERS
Questions testers ask
Where is the Selenium Grid GraphQL endpoint?
For a default local Grid it is commonly `/graphql` on the Router or Standalone address, such as `http://localhost:4444/graphql`. Account for any configured Grid sub-path or reverse-proxy route.
Which GraphQL fields show Grid utilization?
Use `grid.sessionCount` with `grid.maxSession` for current global concurrency, then inspect node-level `sessionCount`, `maxSession`, `slotCount`, status, and stereotypes for the distribution and compatibility detail.
Is totalSlots the same as maximum concurrent sessions?
Not necessarily. A Node can advertise multiple slot stereotypes while its `maxSession` limits simultaneous execution. Display both inventory and concurrency rather than using total slot count as the utilization denominator.
Can GraphQL return errors with HTTP 200?
Yes. A GraphQL response can contain an `errors` array even when the HTTP request succeeded. A poller must validate status, response shape, GraphQL errors, and required data before replacing the last good sample.
Why can the queue grow while Grid shows free capacity?
Global free capacity may belong to incompatible browser or platform stereotypes, a Node may be draining, or the sample may be stale. Compare queued capabilities with free compatible slots before declaring a scheduler fault.
RELATED GUIDES
Continue the learning route
GUIDE 01
Tune Selenium Grid Session Queue Timeouts, Retries, and Batches
Tune Selenium Grid queue timeouts, retry intervals, batches, and polling with measured startup budgets, capability-aware analysis, and safe load tests.
GUIDE 02
Correlate Selenium Grid Sessions with OpenTelemetry Traces
Correlate Selenium Grid OpenTelemetry traces with WebDriver session IDs, structured events, test artifacts, exporter health, and precise failure boundaries.
GUIDE 03
A Production TOML Baseline for Selenium Grid 4
Build a production Selenium Grid TOML baseline with explicit topology, registration trust, Router authentication, node stereotypes, logs, and health checks.
GUIDE 04
Selenium Grid Tutorial: Run Tests Across Browsers
Selenium Grid tutorial explaining architecture, setup, remote WebDriver, browser capabilities, parallel execution, Docker, CI, and debugging tips.