How do you document a type or field in GraphQL SDL, and why is a `#` comment not enough?
answer
- Documentation the client can actually read
- A string literal, not a comment
- Position relative to the definition matters
- Triple quotes for more than one line
basics
~20 sPut a string literal — usually a triple-quoted block string — immediately before the definition. That description is part of the schema and readable through introspection. A # comment is ignored by the parser and never reaches a client.
solid answer
~50 sA **description** is a string literal written immediately *before* the definition it documents, and it is part of the type system rather than a comment. Descriptions may sit on the schema definition, on type definitions, on field definitions, on field arguments, on input object fields, on enum values and on directive definitions — anywhere a reader might need help. Single-quoted strings work for one line; the triple-quoted **block string** is the normal choice because it spans lines, strips the common leading indentation, and processes no escape sequences except an escaped triple quote. The specification says description contents are Markdown, which is why explorers and generated documentation render them. A `#` comment is an ignored token: it is dropped at parse time, so it never appears in introspection, in a printed schema, or in anything generated from one. Type extensions are the one construct that cannot carry a description.
code
graphql · 25 lines"""
A single physical seat on an aircraft.
Identified by the number printed on it, such as `14C`.
"""
type Seat {
"The number printed on the seat."
number: String!
"""
Whether the seat may be sold.
A blocked seat is still returned so the map keeps its shape.
"""
blocked: Boolean!
}
# This comment is invisible to every client of the schema.
enum CabinClass {
"Lie-flat seats in the forward cabin."
BUSINESS
"Standard seats behind the wing."
ECONOMY
}go deeper
Remember the two facts that matter day to day: a description is a string written before the definition, and a # comment is thrown away by the parser. Use triple quotes whenever the text runs past one line.
Explain where descriptions are permitted — including arguments and enum values — and what the block-string form does with indentation and escapes. Know that a type extension is the construct that cannot carry one.
Treat descriptions as part of the published contract: they reach every consumer that can introspect, so internal remarks do not belong in them, and deprecation state belongs in a directive where tooling can act on it rather than in prose.
Decide how documentation quality is enforced. Descriptions are the only documentation guaranteed to stay with the schema, so a rule requiring them on public fields, arguments and enum values is worth more than any external document a team maintains by hand.
## Documentation that ships with the contract Most API documentation drifts because it lives somewhere the API does not. GraphQL closes that gap by making documentation part of the type system: a **description** attached to a definition travels with the schema, is readable through introspection, and therefore shows up wherever the schema does — an explorer, generated reference docs, the output of a typed client generator, a registry's schema view. The syntax is deliberately plain. A description is a string literal placed **immediately before** the definition it documents: ```graphql """ A single physical seat on an aircraft. Seats are identified by the number printed on them, such as `14C`, which is unique within one aircraft but not across a fleet. """ type Seat { "The number printed on the seat." number: String! """ Whether the seat may be sold. A blocked seat is still returned so the map keeps its shape; it is blocked for crew rest, a jump seat, or a broken recliner. """ blocked: Boolean! } ``` Position is the whole rule: before, not after, and not inside the braces as a first entry. A string in any other position is either a syntax error or a different construct entirely. ## Where descriptions are allowed Almost everywhere a definition exists: the schema definition itself, object, interface, union, enum, input object and scalar type definitions, field definitions, the arguments of a field, the fields of an input object, individual enum values, and directive definitions. Argument and enum-value descriptions are the ones teams forget and the ones readers most need — `CabinClass.PREMIUM` means something specific to an airline, and the field's own description is the wrong place to explain it. The exception is a **type extension**, which has no description slot in the grammar at all. The type's description belongs with its original definition. Fields declared inside an extension carry their own descriptions normally, so an extending team can document what it added; it just cannot re-document the type. ## Block strings The triple-quoted block string is what descriptions are normally written with, and it has three properties worth knowing: * It spans lines, so a description can have paragraphs. * Common leading whitespace is stripped, so a description indented to match the surrounding SDL does not arrive at a client with four spaces on every line — which would otherwise render as a code block, since contents are Markdown. * No escape sequences are processed inside it except `\"\"\"`, which lets a description contain a literal triple quote. A backslash inside a block string is just a backslash, which is convenient for anything regex-shaped. A single-quoted string is perfectly legal for a one-liner and is common on fields where a sentence is enough. ## Why a comment is not a description `#` starts a comment, and comments are **ignored tokens**: the parser discards them along with commas and whitespace. Nothing downstream ever sees them. So a file full of carefully written `#` notes produces a schema with no documentation at all — the notes help the next person reading the SDL and nobody else. The team that discovers this usually discovers it from a consumer asking what a field means while looking at an explorer that shows an empty description panel, with the answer sitting in the repository three lines above the field. The conversion is mechanical: turn the `#` into quotes and move it, if necessary, so it sits directly before the definition. ## What a description is not It is not a place for deprecation state. A field being deprecated, and the reason for it, are carried by a directive designed for that, and tools treat that state as structured data — they strike the field through, exclude it from suggestions, and count its usage. A sentence in the description saying “don't use this” gets none of that treatment. It is also not free of consequence. A description is part of the published schema, which means it is visible to every consumer that can introspect — internal notes, ticket numbers, and remarks about which downstream system is unreliable do not belong in one. ## In an interview Nobody is turned down for not knowing this, which is exactly why it makes a pleasant question: it separates people who have authored a schema from people who have only consumed one. The complete answer is short — a string before the definition, block strings for anything multi-line, Markdown by specification, readable through introspection, and comments are dropped.
- Can a type extension carry a description?No — the extension grammar has no description slot, so a type's documentation belongs to its original definition. Fields declared inside the extension carry their own descriptions as usual, so the extending team can still document what it contributed.
- Where does the description of a field argument go?Immediately before the argument inside the field's argument list, exactly as a field description sits before the field. Argument and enum-value descriptions are the ones most often skipped and the ones consumers most often need.
- Why does the specification strip common indentation from a block string?So a description can be indented to match the surrounding SDL without that indentation becoming part of the text. Since description contents are Markdown, uniformly indented lines would otherwise render as a code block in every explorer and generated document.
saying these in an interview costs you the question
- Thinks a # comment appears in the schema for clients
- Places the description after the definition
- Believes only types, not fields or arguments, can be described
- Assumes a description must fit on one line
- Confuses a deprecation reason with a description
- Puts internal notes in a description that every consumer reads