In a Ggr and Selenoid cluster, which setting actually caps how many sessions run at once?
answer
- the router never runs a browser
- a weight is a ratio, not a ceiling
- the cap lives downstream, and it waits
- per host, not per account
- a quota file grants reach, not concurrency
basics
~20 sSelenoid's server-side limit flag does, capping simultaneous container runs on each Selenoid host. Ggr has no concurrency ceiling at all; the count attribute in its quota file is a relative host weight for load balancing, not a cap.
solid answer
~50 sThe ceiling lives downstream, in Selenoid. Its `-limit` flag, whose help text reads "Simultaneous container runs", is a server-wide gate: a slot is taken as a session is created and released when it is deleted, and everyone reaching that host draws on it. A full gate makes the request wait rather than refusing it, and it is still the only place capacity is enforced. Ggr — the load balancer in front, also unmaintained by its own README — has **no concurrency flag whatsoever**. The `count` attribute on a `<host>` element in a Ggr quota file is, in Ggr's own words, "the relative host weight allowing to adjust the load to every host", and Ggr picks hosts by weighted random selection. So raising `count` never buys capacity; it just aims more traffic at a host that still has its own cap. A quota file grants reach, not concurrency.
code
xml · 11 lines<qa:browsers xmlns:qa="urn:config.gridrouter.qatools.ru">
<browser name="chrome" defaultVersion="latest">
<version number="latest">
<region name="rota-dc">
<!-- count is a relative host weight, never a ceiling -->
<host name="rota-selenoid-a.internal" port="4444" count="1"/>
<host name="rota-selenoid-b.internal" port="4444" count="3"/>
</region>
</version>
</browser>
</qa:browsers>go deeper
Know which component does what: the router picks a host, the browser server starts the container. If someone asks where the limit is, point at the server that runs browsers, not at the thing your tests connect to.
Be ready to explain the count attribute correctly and say why the name misleads. Describe weighted random routing in one sentence, name Selenoid's server-side limit as the actual gate, and say that a full gate's default is to make callers wait.
Expect a stalled-cluster scenario. Show that you would measure the real ceiling across the reachable hosts before touching a weight, and that you know sharing an account means sharing that ceiling.
Own the account model. Decide which workloads get their own credentials and their own hosts, accept that a per-host cap makes the cluster ceiling a moving sum, and be explicit about what happens when a host is lost.
A self-operated container grid usually has two moving parts: a router that decides *where* a session goes, and a server that decides *whether* it can start. Confusing the two is the most common mistake in operating one, and both Aerokube tools involved — Ggr and Selenoid — declare themselves unmaintained in their own READMEs, so what follows is worth learning as a shape rather than adopting as a stack. ## Two products, two jobs - **Ggr** is a lightweight active load balancer. It authenticates the caller, reads that account's quota file, chooses a downstream host, and proxies. - **Selenoid** is the thing that actually starts a browser container and holds the session open. The router never runs a browser, which resolves most of the confusion below. ## What Ggr's `count` really is A Ggr quota file is XML: a `browser` element with a `defaultVersion`, one or more `version` elements, each holding `region` elements, each holding `host` elements with `name`, `port` and `count`. The attribute name invites a misreading, and Ggr's own documentation answers it directly, calling `count` "the relative host weight allowing to adjust the load to every host depending on its capacity". Ggr's host selection sums the weights and draws from them at random in proportion. So: - Weights change the **ratio** of requests between hosts, never the total. - A weight is not consumed and not released; nothing counts down. - Setting a weight higher than a host can serve adds no capacity; it just sends more traffic to a host that will hit its own cap sooner. - Ggr's flags are about routing and access — quota directory, users file, guest access, creation timeout, graceful shutdown — with no concurrency flag among them. ## Where the ceiling actually is Selenoid's `-limit` sizes a server-wide gate. A slot is taken as a new-session request is admitted and released when the session is deleted — including when Selenoid deletes an abandoned session itself after its idle timer fires. Three properties matter operationally: 1. It is **per Selenoid host**, so a cluster's true ceiling is the sum across its hosts, and that sum changes when a host goes down. 2. It is **not per account**. Everyone whose sessions land on that host draws from the same gate, whatever their quota file says. 3. Its default when full is **a wait, not a refusal**. Selenoid holds the request until a slot frees or the client gives up; refusing on capacity is opt-in, through Selenoid's `-disable-queue` flag or its `X-Selenoid-No-Wait` header. So what a caller sees on a saturated cluster is usually Ggr's own session-creation timeout expiring in front of a request still queued downstream. | | Ggr's `count` | Selenoid's `-limit` | |---|---|---| | What it is | A relative host weight | A cap on simultaneous container runs | | Where it lives | A per-account quota file | A flag on each Selenoid server | | Scope | One host's share of routed traffic | Every session on that host | | Effect of raising it | More traffic aimed at that host | More browsers allowed to run there | | Effect of exhausting it | Nothing; weights do not run out | New sessions wait to be admitted | ## What a quota file gives you instead A Ggr quota file is an **entitlement catalogue**, named after an account in the credentials file. It says which browsers, which versions, which regions and which hosts that account may reach. That is a real control, and it is not a concurrency allowance. The consequence is the one that bites: two pipelines authenticating as the same account hold the same entitlement, so they can reach the same hosts and contend for the same gate. If a nightly regression run and a pull-request check must not starve each other, separating them is an authentication decision — different accounts pointed at different hosts — not a matter of editing a weight. ## How this goes wrong in practice A hospital rota planner's suite runs against a Ggr-fronted cluster and starts stalling under load. The instinct is to raise the weight on the biggest host, and the stall gets worse: more of the traffic is now aimed at a host whose gate is already full, so those sessions wait longer while quieter hosts stay idle. The correct sequence is: 1. Establish the real ceiling by adding up the `-limit` values configured on the hosts your account can reach. 2. Compare that with how much concurrency the suite asks for, and with who else authenticates as the same account. 3. Set weights to *reflect* each host's capacity, which is exactly what Ggr's documentation recommends, rather than to express a preference. 4. Change the ceiling only where the ceiling is: on the Selenoid servers, and only as far as their CPU, memory and shared-memory budget genuinely allow. ## What an interviewer is listening for - That you name the component that holds the cap rather than the one you talk to. - That a full gate makes callers wait rather than refusing them. - That `count` is a weight and you can say so without being led to it. - That a per-host cap makes a cluster's ceiling a sum, not a single number in a file. - That an account's quota is about reach, and that sharing an account means sharing that reach.
- A nightly run and a pull-request check keep starving each other on your cluster. What do you change?Not the weights. Give them separate accounts in Ggr's credentials file with quota files pointing at different hosts, so the two workloads stop drawing on the same gate. If they must share hosts, the honest answer is that the cluster's ceiling is too low for both, and the fix is more Selenoid capacity rather than a routing tweak.
- How do you work out what your cluster can actually run at once?Add up the configured limit on each Selenoid host your account's quota file can reach, and treat that sum as the ceiling. It is not visible from Ggr, it changes when a host is down or removed from the quota, and it is shared with every account whose sessions land on those hosts.
- Ggr's documentation suggests setting count to the number of browsers a host can run. Does that make it a cap?No, it makes it a good weight. The recommendation is about proportion: if weights track each host's real capacity, weighted random routing spreads load evenly instead of overloading a small host. Ggr still never refuses on that basis. Whether a session starts — or waits — is decided further down, by the Selenoid the request was routed to.
Ggr's count is a splitter on a water main, deciding what share of the flow goes down each pipe; Selenoid's limit is the tap at the end of a pipe — the only thing that can actually stop the flow, and what it usually does is back the water up rather than turn it away.
saying these in an interview costs you the question
- Reads the count attribute as a per-host session cap
- Believes a busy cluster refuses new sessions instead of queueing them
- Thinks a quota file grants an account its own concurrency
- Raises a host weight expecting extra capacity to appear
- Treats a cluster ceiling as one setting rather than a sum
- Assumes separate pipelines on one account are isolated