In GraphQL, are a mutation's root fields executed serially or in any order?
answer
- Only one operation type is constrained
- Side effects are what make order matter
- The constraint stops at the root fields
- Everything nested must be side-effect-free
- An ordering guarantee, not a transaction
basics
~20 sSerially. GraphQL requires a mutation's top-level fields to run one after another in document order, so their side effects are ordered. A query's root fields are side-effect-free, so a server may run them in any order.
solid answer
~40 sThe specification draws the line at the **root** selection set of a mutation: those fields execute serially, in the order the document lists them, each finishing before the next begins. That is what lets a client write `calibrateSensor` and then `retireSensor` in one document and rely on the first write landing first. Everywhere else — a query's root fields, and every field nested beneath any root field, mutation included — execution may happen in any order or concurrently, because the spec requires resolution outside top-level mutation fields to be side-effect-free and idempotent. Serial means ordered, not transactional and not halt-on-failure: a root field that errors is nulled and the next root field still runs. Response-map key order follows the document either way, so you cannot infer execution order from a response body.
code
graphql · 11 linesmutation ClosePaddock {
calibrateSensor(id: "snsr_4471", offsetC: 0.35) {
serial
lastCalibratedAt
paddock { name sensorCount }
}
retireSensor(id: "snsr_2038") {
serial
retiredAt
}
}go deeper
Recall the one-line rule: a mutation's top-level fields run one after another in the order written, while a query's may run in any order. Being able to say which operation type is constrained is what this question checks.
Explain where the boundary sits — the root selection set only — and why it sits there: the spec requires resolution below top-level mutation fields to be side-effect-free and idempotent, which is what makes reordering them safe.
Show the operational consequence. A six-field mutation document costs the sum of six writes on one connection under one timeout, and leaves the earlier writes committed when a later field raises. Be ready to advise a client to split them.
Own the contract decision: whether clients may compose multi-write documents at all, or whether each business transaction gets one coarse root field, so ordering and atomicity are properties you designed rather than side effects of document order.
## The rule, stated exactly GraphQL's execution algorithm has exactly one place where ordering is mandatory. When the operation is a **mutation**, the root selection set is executed *serially*: the executor takes the first field in document order, resolves it, completes its value, and only then moves to the second. When the operation is a **query**, the root selection set is executed normally, which the specification defines as permitting the fields to be executed in any order, including concurrently. That is the whole rule, and its two halves are usually misremembered together. People extend "serial" to the entire mutation document, and they read "any order" as a promise of parallelism. Neither holds. ## Why the line is drawn at the root The justification is side effects. A mutation exists to change something, and a client that writes two changes in one document plainly means them in the order written. Serial root execution is what makes that expectation legal to hold rather than a bet on the server's scheduler. Below the root, the specification requires the opposite: resolution of fields other than top-level mutation fields must be free of side effects and idempotent. Because nothing underneath is allowed to mutate anything, reordering it or running it concurrently cannot change the outcome — and that is exactly what licenses an executor to fan out. So the rule is not arbitrary. It is the narrowest constraint that still preserves the only ordering a client can meaningfully depend on. ## Where the boundary falls, concretely ```graphql mutation ClosePaddock { calibrateSensor(id: "snsr_4471", offsetC: 0.35) { serial paddock { name sensorCount } } retireSensor(id: "snsr_2038") { serial retiredAt } } ``` `calibrateSensor` runs to completion — its resolver, its value completion, its whole subtree — before `retireSensor` begins. Inside `calibrateSensor`'s payload, `serial` and `paddock` may resolve in either order or at the same time, and `paddock`'s own children likewise, because those are not top-level mutation fields. Had the same two fields been written under `query`, a conforming server could have run them in either order, and a client depending on one preceding the other would be depending on an implementation detail rather than the specification. ## Four things serial does not give you **It is not a transaction.** Each root field's resolver commits its own work as it goes. There is no shared unit of work and no rollback, and the specification defines neither. A three-write document that fails on the second leaves the first write in place. **It does not halt on failure.** A field error nulls that field and records an entry in `errors`, and execution continues with the next root field — which, for a mutation, means performing the next write. **It is not a concurrency guarantee for queries.** "Any order" includes "one after the other". A single-threaded executor that runs query root fields strictly sequentially is perfectly conformant; the permission is an optimisation a server may decline. **It does not shape the response.** The response map's key order follows the document's field order for both operation types, so you cannot read execution order — or overlap — off a response body. Two query root fields appear in document order whether they ran together, in sequence, or in reverse. ## The operational consequence Because a mutation's root fields cannot overlap, the wall-clock cost of a multi-write document is the **sum** of its writes, not the maximum. A client that packs six calibration writes into one request to save round trips buys one network round trip and pays six serialized backend latencies under a single request timeout. If the sixth write trips that timeout, the first five have already committed and the caller learns nothing about which. At a peak of 1,200 requests per minute, documents shaped like that also hold a server worker for the full sum rather than the longest leg, which is usually where a concurrency limit bites first. The advice follows directly from the rule. If the writes are genuinely independent, send them as separate requests and let the network parallelise them. If they are genuinely one business change, expose one root field whose resolver owns the sequence, so ordering and atomicity are the server's property rather than something emergent from document order. Composing many root mutation fields is legal and ordered, and it is rarely what the client actually wanted. ## How to answer it State the rule in one sentence, then immediately mark the boundary — root fields only, mutation only — and then say what serial does not mean. Most candidates produce the first sentence and stop. The boundary and the non-guarantees are what separate a memorised fact from having debugged one of these.
- Does the serial rule apply to the fields nested inside a mutation's payload type?No. Only the root selection set of the mutation operation is serial. Once a root field returns, its own selection set — the payload's fields and everything below them — is executed like any query selection set: in any order, and concurrently if the server chooses. The spec licenses that by requiring resolution outside top-level mutation fields to be free of side effects and idempotent.
- If mutation root fields are serial, why is a two-field mutation document still not atomic?Because serial only orders the calls. Each root field's resolver commits its own work as it goes; there is no shared transaction, no rollback and no early exit on error. If the second field raises, the first field's write has already happened and stays. Atomicity, where you need it, comes from putting the whole sequence behind one root field whose resolver owns the transaction.
- May a server legally execute a query's two root fields one after the other instead of in parallel?Yes. The spec permits any order, which includes strictly sequential; it never requires concurrency. Parallelism is an optimisation a server may take or decline, and a single-threaded executor is fully conformant. A client must therefore assume neither ordering nor overlap between query root fields, and must not read either off the response.
Serial root execution is a queue at one teller, not a locked vault: the customers are served strictly in line, and nothing undoes the first transaction because the third one fails.
saying these in an interview costs you the question
- Says every field in a mutation document resolves serially
- Claims serial execution makes the mutation a transaction
- Thinks a failing root mutation field stops the later ones
- Says query root fields are guaranteed to run in parallel
- Infers execution order from the response's key order
- Believes the spec forbids running query root fields sequentially