Service capabilities
At a glance​
- Identifier: #1208
- Stage: RFC0: Strawman
- Champion: @benjie
- PR: Service capabilities
- Related:
- #1163 (Allow clients to disable error propagation via request parameter (take 2))
Timeline​
- Spec PR created on 2026-01-15 by benjie
- 13 commits pushed on 2026-01-15:
- Extract service capabilities by @benjie
- Reserve example.* identifiers by @benjie
- Replace default capabilities by @benjie
- Update syntax, add examples by @benjie
- Editorial by @benjie
- Extend syntax by @benjie
- Note that IANA reserved domains are also reserved by @benjie
- Clearer by @benjie
- Lee suggested to not use + by @benjie
- Move Service stuff to bottom of lists by @benjie
- More editorial by @benjie
- Format by @benjie
- Typo by @benjie
- Added to 2026-01-15 WG agenda
- Mentioned in 2026-01 WG notes
(Extracted and reworked from the error behaviors PR (#1163) to stand alone, since it has broader utility and can progress faster alone.)
This PR introduces "service capabilities" - a mechanism for GraphQL services to advertise features and configuration that exist outside the type system - for example support for syntax features (executable descriptions, fragment arguments, document directives, etc), details of transport support (websocket endpoint, SSE endpoint, how to be notified of new schema versions), and other details that can enable automated client configuration.
Motivation​
In addition to being a prerequisite of the error behaviors proposal, this is a desired feature for composite schemas and a key component of The GraphQL Golden Path Initiative (specifically enabling client auto-configuration).
The goal is that a user can point tooling at a GraphQL endpoint and much of the configuration can be implied based on the service's advertised capabilities - this massively reduces the amount of "out of band" communication required.
Example use cases:
- Does the service support fragment arguments, or must the client transpile them?
- Does it support customizing error propagation behavior?
- Are subscriptions available over WebSockets? If so, what endpoint and protocol?
- Does it support incremental delivery (
@defer/@stream)? Which version?- Does it support automated document persistence? Which protocol?
Why "capabilities" not "metadata"?​
Capabilities inform automated tooling/client decisions and actions. Metadata is ancillary and often intended for human consumption. The name "capabilities" is intentional - it signals the purpose and discourages using this system as a dumping ground for arbitrary metadata. Every capability should be actionable by clients or tooling.
Design​
Introspection via
__service: __Servicemeta-field (similar to__schema: __Schema):type __Service {
capabilities: [__Capability!]!
}
type __Capability {
identifier: String!
description: String
value: String
}Support can be probed via:
{ __type(name: "__Service") { name } }- if no result, then the service does not support service capabilities.SDL syntax​
Slightly changed from previous proposals, here's the syntax I now propose:
service {
"Descriptions on operations and fragments are supported"
capability graphql.operationDescriptions
"WebSocket transport is supported via the given endpoint"
capability example.transport.ws("wss://api.example.com/graphql")
}
extend service {
capability com.example.customFeature
}Notes on this choice:
- Capabilities without "values" should look neat
- Capabilities with values followed by capabilities without descriptions should not introduce easy syntax clashes (
service { capability foo.bar "Value" capability foo.baz }would apply"Value"as the description forfoo.bazrather than the value forfoo.bar)- The
extendsyntax feels very natural- Avoids double-nesting of curly braces
- Leaves space for additional
serviceproperties in future- Inserting other keywords between capabilities is acceptable, in the same way that inserting different directives between repeatable directives is acceptable
- A directive-based syntax could be used (
service @capability(identifier: "...", value: "...")), but theservicekeyword already introduces new syntax so it doesn't seem necessary to be constrained to using ugly directives when a neater and more palatable syntax is available; this also allows for descriptions for each capability.Capability identifiers​
A
QualifiedNamesyntax (Name(.Name)+) inspired by reverse-domain notation encourages global uniqueness. Thegraphql.prefix is reserved for official GraphQL Foundation specifications (not just the main spec; e.g.graphql.http.*could be used by the GraphQL-over-HTTP spec).