How does a GraphQL server choose which operation to run in a multi-operation document?
answer
- The caller says which one
- One operation, the name is optional
- Two operations, ambiguity is fatal
- Names unique within a single document
- Errors present, data key absent entirely
basics
~10 sBy the operationName the caller supplies. With exactly one operation in the document the name may be omitted; with two or more, a missing or unmatched operationName is a request error and nothing executes.
solid answer
~50 sA GraphQL request carries an optional `operationName` alongside the document, and the server resolves it before execution. If no name is supplied and the document defines exactly one operation, that operation runs. If no name is supplied and the document defines two or more, that is a **request error**. If a name is supplied, the operation carrying it runs, and if none carries it that is a request error too. There is no fallback: the server never runs the first definition by position and never merges results. Two validation rules keep the lookup deterministic — operation names must be unique within a document, and an anonymous operation must be the only operation in its document. A request error is raised before any resolver runs, so the response carries an `errors` entry and **no `data` key at all**, rather than a `data` object full of nulls.
code
graphql · 12 linesquery ClinicianDay($clinicianId: ID!) {
clinician(id: $clinicianId) {
fullName
appointmentsToday { id startsAt }
}
}
query ClinicBacklog($clinicId: ID!) {
clinic(id: $clinicId) {
unbookedSlotCount
}
}go deeper
Know that one document can define several operations and that the caller then has to say which one by name. The operation name is not decoration.
Walk the resolution rules exactly — no name with one operation, no name with several, a name matching nothing — and say what the response looks like in each failing case, including the absent data key.
Connect it to operating a service: unnamed or duplicated operation names make per-operation latency and error rates unattributable, which is precisely what you need when one read degrades only under peak load.
Own the naming standard and its enforcement. Uniqueness beyond a single document is your convention rather than the specification's, and it is the precondition for per-operation budgets, cost ceilings and a document registry.
## The selection step, precisely An executable document may define several operations. Something has to choose one, because a GraphQL request executes exactly one operation — never all of them, never the first one by position. That something is a request parameter conventionally called `operationName`, supplied by the caller alongside the document. Before execution the server resolves it, and the specification's rules are short enough to memorise: - `operationName` is **not** supplied and the document defines **exactly one** operation → that operation is selected. - `operationName` is **not** supplied and the document defines **two or more** operations → **request error**. - `operationName` **is** supplied → the operation carrying that name is selected; if no operation carries it, **request error**. There is no fallback. A server does not run the first definition, does not run the only query when the others are mutations, and does not merge anything. ## Why the outcome is always deterministic Two validation rules make the lookup unambiguous, and they are worth naming because interviewers probe for them. **Operation name uniqueness.** Each named operation definition in a document must have a unique name. So a supplied name can never match two definitions. **Lone anonymous operation.** If any operation in a document is anonymous, it must be the only operation there. So a document can never contain a nameless operation that a name-based lookup would be unable to reach. Both are checked statically, before execution. A document that violates either one never gets as far as operation selection. ## What the failure looks like on the wire A failed selection is a **request error**, not a field error, and the distinction shows up in the response shape. A field error leaves you with a `data` object containing a null in the failing position and an `errors` entry describing it — the request ran and part of it worked. A request error means nothing ran, so the response has an `errors` entry and **no `data` key at all**: ```json { "errors": [ { "message": "Operation name required: the document defines more than one operation." } ] } ``` The message text is not specified — every server words it differently — but the absence of `data` is. A client that reads `response.data.appointment` without checking for `errors` first will fail on a missing property rather than on a null, which is a surprisingly common way for this bug to present. ## Uniqueness within a document versus across a codebase Here is the spec-versus-convention line, and it is the follow-up an interviewer reaches for. The specification requires operation names to be unique **within one document**. It says nothing whatsoever about two different documents in your application both defining `query AppointmentDetail`. That is legal by the specification and no server will reject it. Requiring names to be unique across an entire client codebase is a **convention**, enforced by a lint rule, and it exists for reasons that have nothing to do with execution: - **Attribution.** Per-operation latency, error rate and call volume are keyed by name. Two unrelated documents sharing `AppointmentDetail` merge into one line on every dashboard. - **Registries.** Any workflow that extracts documents at build time and registers them by name needs the name to identify exactly one document. - **Budgets and limits.** Per-operation timeouts, cost ceilings and rate-limit tiers are configured by name. ## Where it bites in production Consider a hospital appointment graph running a 1,200-request-per-minute peak at morning clinic opening, and an operation that times out only in production — never in staging, where the dataset is small enough that the same document returns in under a second. Everything you need to find it is per-operation: which name's p99 crossed the timeout, when it started, which deploy introduced the selection set that did it, how many of the 1,200 requests per minute are that operation. If the client ships anonymous operations, the server's only key is `null` and none of those questions can be asked. If two documents share a name, the slow one's p99 is diluted by the fast one's volume, and the dashboard looks merely unhealthy rather than pointing at a culprit. That is the real reason the naming discipline is worth arguing for: not because a server would otherwise pick the wrong operation — the rules above make that impossible — but because the name is the only identifier your operational tooling has, and it is chosen months before you need it.
- The document defines three operations and no operationName is supplied. What does the response look like?A request error: the response object carries an `errors` list and no `data` key at all. That is different from a field error, where `data` is present with a null in the failing position and the rest of the result filled in. Here nothing was executed, so there is no partial data to report. A client that reads a path off `data` without checking `errors` first fails on a missing property.
- Does the specification require operation names to be unique across a whole client codebase?No. The validation rule requires uniqueness only within a single document; two different documents in your application may both define `query AppointmentDetail` and no server will object. Requiring names to be globally unique across a codebase is a widespread convention enforced by lint rules, and it exists so that metrics, logs, per-operation budgets and any document registry can key on a name identifying exactly one document.
- What happens when operationName names an operation the document does not define?It is a request error and nothing executes, exactly as with an ambiguous selection. This is the usual symptom of a stale artefact — a client shipping a name the deployed document no longer contains, or a registry entry pointing at a renamed operation. The whole request fails rather than degrading, which at least makes the mismatch loud.
saying these in an interview costs you the question
- Says the server runs the first operation by default
- Thinks all operations in the document execute
- Believes a bad operationName returns data with nulls
- Claims the specification requires globally unique operation names
- Says operation names exist only for an explorer's dropdown
- Treats a request error as just another field error