skip to content

questions

3

Which name rules does the GraphQL specification enforce, and which are only convention?

level: juniorimportance: must knowfreq 54%

answer

  1. Most of it is habit, not law
  2. The grammar is the short part
  3. Case matters, everywhere
  4. One prefix is already taken
  5. Two underscores belong to introspection

basics

~20 s

The specification fixes only the character grammar - a leading letter or underscore, then letters, digits or underscores - case sensitivity, and the reservation of any name starting with two underscores. camelCase fields and PascalCase types are ecosystem habit, not rules.

solid answer

~40 s

Three things are actually specified. A name matches `/[_A-Za-z][_0-9A-Za-z]*/`, so no hyphens, dots or leading digits. Names are **case-sensitive**, so `grossPayYtd` and `grossPayYTD` are two different fields. And no name in the type system may begin with two underscores - that prefix is reserved for introspection, and a conforming server rejects `type __Payslip` when it builds the schema, not at request time. Enum values add two more: a value may not be named `true`, `false` or `null`, and the specification *recommends* all caps without requiring it. Everything else - camelCase for fields and arguments, PascalCase for types, SCREAMING_SNAKE for enum values, the `Input` suffix - is convention. It is near-universal because the specification's own built-in directives and introspection types are written that way, but nothing enforces it except review and linting.

code

graphql · 7 lines
graphql
type Employee {
  employeeId: ID!
  Employee_ID: ID!
  grossPayYtd: Int!
  grossPayYTD: Int!
  _internalRef: String
}

go deeper

for a junior

Be ready to state the grammar, case sensitivity and the reserved double-underscore prefix, then say plainly that camelCase and PascalCase are conventions. Interviewers ask this to see whether you can tell a rule from a habit.

for a middle

Explain where each rule is enforced: an illegal character fails at parse, a reserved prefix fails when the schema is built, and a broken convention fails nowhere - it surfaces later in generated identifiers and in review.

for a senior

Treat naming consistency as a contract property rather than taste. Uniform casing is what makes generated clients, lint rules and schema search work across a large schema, and the cost of drift is paid by every consumer.

for a principal

Own the position that naming style is decided once, written down, and enforced mechanically, because retrofitting a convention onto a shipped schema means renaming - the expensive class of change - rather than reformatting.

## The specification's name grammar is short Every name in GraphQL — object and input type names, field names, argument names, directive names, enum value names, variable names, fragment names — comes from one lexical production. A name begins with a letter or an underscore and continues with letters, digits or underscores, which is usually written `/[_A-Za-z][_0-9A-Za-z]*/`. That is the whole syntax rule. No hyphens, no dots, no colons, no spaces, no leading digit, no punctuation of any kind. If you have ever tried to surface a column called `gross-pay-ytd` or a payload key called `401k.match` on a payroll graph as a field, this is the rule that stopped you, and the remedy is a mapping inside the server: GraphQL has no escaping or quoting syntax for names. ## Names are case-sensitive `grossPayYtd` and `grossPayYTD` are two different names, and a type may legally declare both. Nothing folds case anywhere in the language — not in the schema, not in a document's selection set, not when a response key is written out. This matters more than it sounds, because a schema assembled from several sources is exactly where you end up with `employeeId` on one type and `employeeID` on another, and the two are unrelated names that every consumer must remember separately. ## The one reserved prefix The specification reserves names beginning with two underscores for the introspection system, and it states this as a requirement on the type system rather than as advice. A conforming implementation rejects `type __Payslip` or a field named `__auditTrail` when it builds the schema — before any request is executed, not at query time. This is the only naming rule in the specification that has anything to do with meaning rather than characters, and it is the only one that can make a schema fail to build for a reason a reader would call semantic. A single leading underscore is legal: `_internalRef` builds fine. It reads as a near miss, and most reviewers will ask for it to go. ## Enum values carry two more real rules An enum value is written as a bare name, so the specification excludes the three names that already mean something in the input language: an enum value may not be `true`, `false` or `null`. Beyond that, the specification *recommends* — in one of the very few places it makes a stylistic recommendation at all — that enum values be written in all caps. A recommendation is not a rule. `enum PayFrequency { weekly biWeekly semiMonthly }` builds and executes; it simply looks wrong to every reader and to every generator's default identifier mapping. ## Everything else is habit camelCase for field and argument names, PascalCase for every named type, SCREAMING_SNAKE_CASE for enum values, and the `Input` suffix on input object types are ecosystem conventions with no specification backing whatsoever. The reason they are so uniform is that the specification follows them itself: its own introspection types, its built-in directives — `@skip`, `@include`, `@deprecated`, `@specifiedBy` — and their arguments `if` and `reason` are all written in exactly that style. Implementations copied the style of the document that defined them, and generated schemas copied the implementations. ## Why breaking a convention still costs you First, generated code. A typed client generator maps schema names onto identifiers in a target language, and each one has its own transformation rule. Give it `employee_id`, `employeeId` and `Employee_ID` as three fields on the same type and you can get mangled or colliding identifiers in the output, or an identifier that no longer resembles the field it came from. A name that is legal GraphQL is not automatically a distinct, legal identifier downstream. Second, readers. A schema is read far more often than it is written, and it is read in autocompletion lists and documentation panes where the only cue about what kind of thing a name is is its case. In a schema where types are PascalCase and fields camelCase, `Payslip` and `payslip` are instantly distinguishable as a type and a field. Break that and every reader has to slow down. Third, the cost of change. Field and type names are the contract: they appear in every document a client has shipped and, for types, in fragment type conditions. Fixing a name later is not a local edit, which is why the convention question is really a question about doing it once, correctly, at the start. ## What the interviewer is testing Two things that pull against each other. The first is that you can tell a rule from a habit: a candidate who says "the specification requires camelCase" has confused what a linter enforces with what the language enforces, and that same confusion tends to show up later as confident wrong claims about what is and is not specified elsewhere in GraphQL. The second is that you follow the habit anyway, without needing a rule to make you. The strong answer is the one that names the real constraints — grammar, case sensitivity, the reserved prefix, the three forbidden enum value names — and then says that everything else is convention that you enforce as if it were a rule.

  • Are `payslipId` and `payslipID` the same field name in a GraphQL schema?
    No. Names are case-sensitive and nothing in GraphQL folds case, so a type may legally declare both and a client selecting one gets exactly that one. This is a common source of drift in a schema assembled from several sources, and it is why consistent casing is worth enforcing even though no rule demands it.
  • What happens if you define a field named `__auditTrail`?
    The schema fails to build. The specification reserves names beginning with two underscores for the introspection system and states it as a requirement on the type system, so a conforming implementation rejects it before any request runs. A single leading underscore - `_auditTrail` - is legal but reads as a near miss and usually gets flagged in review.
  • Does the specification say anything at all about enum value names?
    Yes, two real constraints and one recommendation. An enum value may not be named `true`, `false` or `null`, because those names already mean something in the input language. Separately, the specification recommends that enum values be written in all caps - one of very few style recommendations it makes - but a lower-case enum value builds and executes normally.

saying these in an interview costs you the question

  • Says the specification mandates camelCase field names
  • Thinks GraphQL name matching is case-insensitive
  • Believes the double-underscore prefix is only a convention
  • Claims hyphens or dots are allowed in names
  • Names an enum value null and expects it to parse
  • Cannot say where a bad name is rejected

context

open as a page

Why are GraphQL field names like getEmployee or payslipsFromHrisV2 discouraged?

level: middleimportance: should knowfreq 48%

basics

~20 s

A field names the data it yields, not the call behind it. The operation type already says the request is a read, so get is noise, and a name carrying the backing system becomes a lie the day that system is replaced.

open as a page

GraphQL has no packages, so how do you keep type names unique across many teams?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Every named type in a schema shares one flat pool - the specification requires unique type names and offers no namespaces. Uniqueness has to come from a shared vocabulary: qualify types by domain concept and keep generic nouns out of the pool.

open as a page