Skip to content
chornous.dev

Type two or more letters. Esc closes.

Index of sheets
Theme

Sheet 03 · Writing

All notes

GraphQL caught up: a spec edition, GraphQL.js 17 and an AI pitch

The first full GraphQL spec edition since 2021 added @oneOf inputs and schema coordinates. GraphQL.js 17, the reference implementation, followed in June 2026. The changes for a client team, with a schema you can copy.

Pl. 47 · network drawing generated from the slug “graphql-spec-2025-graphql-js-17”

GraphQL went almost four years without a new spec edition. The September 2025 edition ended the gap, GraphQL.js 17 brought the reference implementation up to date in June 2026, and at GraphQLConf 2026, Apollo's CEO and thirteen sessions made the case for GraphQL as the query language for agents.

  1. Oct 2021

    Previous spec edition.
  2. Sep 8, 2025

    September 2025 edition: more than 100 commits from dozens of contributors.
  3. May 19–20, 2026

    GraphQLConf 2026 in Fremont, California.
  4. Jun 1, 2026

    GraphQL Auxiliary Proposals (GAPs) announced as a home for community-written specs.
  5. Jun 15, 2026

    GraphQL.js 17.0.0. Patch 17.0.2 followed on July 3.

The spec edition

The editors list stability as the first priority, and much of the work fixes inconsistencies and edge cases. The additions you'll use:

  • OneOf input objects. An input type where the client sets exactly one field. People have asked for input unions for years.
  • Schema coordinates. A standard way to point at Type.field or Type.field(arg:), which tooling and error messages can now share.
  • Descriptions on executable documents. You can document the queries themselves as well as the schema. The spec authors note that AI tools benefit from it.
  • Deprecation on more elements, so you can retire an argument or input field the same way you retire an output field.
  • Full Unicode in the language grammar.

@oneOf in practice

Before @oneOf, "look a user up by id or by email" meant two nullable arguments and a runtime check that exactly one arrived. Now the schema says it:

input UserLookup @oneOf {
  id: ID
  email: String
  handle: String
}

type Query {
  user(by: UserLookup!): User
}

The rules follow from "pick one": every field must be nullable and none may declare a default, because a default would supply a second value behind your back. A client that sends { id: "1", email: "[email protected]" } gets a validation error before any resolver runs, and a code generator can emit a union type instead of an object with optional keys.

GraphQL.js 17

From the GraphQL.js v17 release notes and package metadata
ChangeEffect on you
Directives on directivesgraduated from experimental
undefined treated as absenta variable set to undefined behaves as if you never sent it
valueFromAST rejects unknown fieldsonly matters if your tooling calls this deprecated helper
ESM-only build removedone package layout instead of two
Node supportneeds Node 22, 24, 25 or 26+

Incremental delivery with @defer and @stream keeps getting refinements in 17, including exported validation rules. The change I'd test first is undefined-as-absent. Over HTTP it changes little, because JSON.stringify drops undefined keys before they leave the client. It shows up where variables never touch JSON: server-side code that calls execute() itself, and tests that pass { id: undefined }. Those now behave as if the key were missing, so run that code against 17 before you upgrade.

The AI pitch

The GraphQLConf 2026 wrap-up opens with Apollo's CEO Matt DeBergalis saying GraphQL "can and must be the language of AI". Thirteen sessions covered agents, semantic introspection and MCP tool integration. A typed schema with descriptions reads as a machine contract, and an agent can ask for exactly the fields it needs.

Meta's keynote pushed back. Its speakers, whose company runs hundreds of billions of GraphQL calls a day, said some of GraphQL's original promises did not survive contact with thousands of engineers. Shopify's breadth-first execution and a Meta talk on 40,000-field queries showed how much engineering sits behind a query that looks simple.

For a client team this adds up to two schema changes and one test: @oneOf where inputs are either/or, descriptions on the operations your app sends, and a run of any server code or tests that call execute() against GraphQL.js 17.

Sources

Volodymyr Chornous