What is a named fragment in a GraphQL document, and how do you spread one?
answer
- Write the selection once, use it anywhere
- Lives beside the operations, not in the schema
- Three dots, then the name
- The clause after on is a type condition
- Fields land inline, no wrapper key
basics
~20 sA named fragment is a reusable selection set declared once at the top level of a document, on a type condition, and pulled into a selection with the three-dot spread. Its fields land in the response exactly as if written inline.
solid answer
~40 sA named fragment is a top-level definition in an executable document: `fragment ClaimSummary on Claim { claimNumber status reserveCents }`. The part after `on` is its **type condition** - the type whose fields the fragment is allowed to select. You use it with a **fragment spread**, `...ClaimSummary`, written as a selection inside a selection set. Spreading is substitution as far as the response is concerned: the fragment's fields appear at the spread's own level under their normal response keys, with no wrapper key named after the fragment. Fragment names must be unique within a document, and definitions sit beside the operations at the top level, so one fragment can be spread many times, across several operations, and may be defined after the operation that uses it.
code
graphql · 11 linesquery ClaimsQueue {
openClaims { ...ClaimSummary }
escalatedClaims { ...ClaimSummary }
}
fragment ClaimSummary on Claim {
claimNumber
status
reserveCents
policy { policyNumber }
}go deeper
Be ready to write one from memory: the keyword, a name, on SomeType, a selection set, then a three-dot spread at the point of use. Say plainly that the response comes back flat, with no key named after the fragment.
An interviewer expects the mechanics: the type condition must be an object, interface or union; names are unique per document; definitions are unordered; and a spread costs the server exactly what the same fields written inline would cost.
Show where fragments earn their keep and where they mislead - readability of deep documents, the fragment-name collision when one document is assembled from several sources, and the fact that no server-side caching or reuse follows from the name.
Own the convention layer: whether fragment naming is enforced across teams, how fragment libraries are versioned alongside the schema, and how much request-shape vocabulary you are willing to standardise before it becomes coupling nobody can change.
## A fragment is a definition, not a schema construct An executable GraphQL document is a list of definitions, and only two kinds may appear in it: operation definitions (`query`, `mutation`, `subscription`) and **fragment definitions**. A fragment definition has exactly three parts - a name, a **type condition** introduced by `on`, and a selection set: ```graphql fragment ClaimSummary on Claim { claimNumber status reserveCents policy { policyNumber } } ``` None of this reaches the schema. The server does not gain a type, a field or a capability called `ClaimSummary`; the name exists for the lifetime of the request document and nowhere else. Two different callers may each define `ClaimSummary on Claim` with completely different fields, and neither is aware of the other. That is the first thing to be clear about in an interview: a fragment is client-side vocabulary carried inside the request. ## The spread substitutes, it does not nest A **fragment spread** - three dots followed by the name - appears as a selection inside a selection set, alongside ordinary fields: ```graphql query ClaimsQueue { openClaims { ...ClaimSummary } escalatedClaims { ...ClaimSummary } } ``` The executor expands the spread in place, so what comes back is flat: ```json {"data":{"openClaims":[{"claimNumber":"CLM-88214","status":"OPEN","reserveCents":412500,"policy":{"policyNumber":"POL-3391"}}],"escalatedClaims":[]}} ``` There is no key called `ClaimSummary` anywhere in that response, and there never can be. A candidate who expects a nested object named after the fragment has confused a spread with a wrapper. ## The rules the syntax carries **Names are unique within a document.** A document containing two definitions named `ClaimSummary` is invalid whatever their type conditions or contents, and it is rejected before anything executes. This bites when a caller assembles one document out of fragments authored in different places; the usual defence is a naming convention that prefixes each fragment with the view or module that owns it. That convention is a house style, not a rule in the specification - the specification only demands uniqueness inside the one document being sent. **The type condition must be a composite output type** - an object type, an interface or a union. `fragment Amount on Int` is invalid: a scalar has no selection set, so there is nothing for the fragment's body to be checked against. Input object types are ineligible for the same reason; fragments belong to output selection. **Definitions are unordered.** A fragment may be defined after the operation that spreads it, between two operations, or at the very end of the document. Unlike a variable, which must be declared on the operation that uses it, a fragment has no declaration-before-use rule - the whole document is parsed before anything is checked. **Fragments may spread other fragments.** A fragment's selection set is an ordinary selection set, so a fragment can itself contain `...PolicyStamp`. Nesting simply flattens; a fragment may not, directly or through a chain, end up spreading itself. ## Why they are worth having Reuse and readability, in that order. In a claims graph the same "who, what, how much" block is wanted on the queue screen, on the detail screen and in the nightly export, and factoring it out means one edit instead of three. It also keeps very deep documents legible: the deepest document in one insurer's caller bundle reaches 19 levels - claim, related claims, their events, the assigned adjuster, that adjuster's own queue - and reading it at all depends on each level being one named spread rather than forty inline fields. What fragments do **not** buy is server work. A spread resolves exactly the fields it lists, exactly as if they had been typed inline. There is no caching by fragment name, no reuse across requests, and no reduction in resolver calls. The only saving is in the bytes of the request, and only when a fragment is spread more than once. ## Not a function The specification's fragments take no arguments of their own. A fragment can reference variables - a field inside it may carry `@include(if: $showFinancials)` - but those variables belong to the *operation*, and every operation that spreads the fragment must define every variable used anywhere inside it, transitively. Proposals to give fragments their own parameters have circulated for years; a portable document cannot assume them today. A candidate who describes a fragment as "a function you call with arguments" is usually describing an extension a particular client tool added, not GraphQL. ## Saying it in an interview Lead with the definition-plus-spread mechanic and the fact that the response is flat, then the type condition, then uniqueness. If you have thirty seconds more, add the two facts most people get wrong: fragments are invisible to the schema, and they save request bytes rather than server work.
- Can a fragment spread another fragment, and can it be defined after the operation that uses it?Both yes. A fragment's body is an ordinary selection set, so it may contain further spreads, and nesting simply flattens when the executor expands them. Fragment definitions are top-level and unordered, so a fragment may appear before the operation, after it, or between two operations - there is no declaration-before-use rule as there is for variables. The one thing a fragment may not do is end up spreading itself, directly or through a chain.
- Does a fragment need to exist in the schema, or change what the server exposes?Neither. A fragment is part of the request document only. The schema declares no fragments, the server gains no type or field from one, and it forgets the name once the response is written. Two independent callers can define fragments with the same name on the same type, containing different fields, and both requests are perfectly valid because uniqueness is scoped to a single document.
- What happens if a caller merges two libraries of fragments into one document and two names collide?The document is invalid and is rejected before execution - fragment names must be unique within the document being sent, and no rule about type conditions or contents softens that. It is a request error, so nothing resolves and there is no partial data. The common defence is a naming convention that prefixes each fragment with the view or module that owns it; that is a house style, not a requirement of the specification.
A fragment is a named clipboard entry travelling inside the request: you write the selection once and paste it wherever it fits, and nothing about the clipboard itself shows up in what comes back.
saying these in an interview costs you the question
- Thinks a fragment is declared in the schema
- Expects a response key named after the fragment
- Believes fragments must be defined before they are spread
- Says a fragment takes arguments like a function
- Assumes spreading a fragment reduces server-side work
- Thinks two fragments may share a name if conditions differ