Versioning

Unlike REST APIs, GraphQL schemas do not use URL-based versioning (like /graphql/v2). Most schema changes are additive and non-breaking: adding new types and new fields does not affect existing queries. Removing a field or changing its nullability, however, is a breaking change.

GraphQL provides two directives to manage the lifecycle of schema elements:

  • @deprecated signals that a field is being phased out and consumers should migrate away.
  • @requiresOptIn signals that a field is not yet stable and requires explicit consumer consent.
GraphQL
type Query {
  users: [User] @deprecated(reason: "Use the `authors` field instead")
  authors: [User]
  recommendations: [Book] @requiresOptIn(feature: "experimentalRecommendations")
}

Deprecation#

You can deprecate output fields, input fields, arguments, and enum values. Deprecated elements remain functional but are flagged in introspection, warning consumers to migrate.

Warning

You cannot deprecate non-null arguments or input fields that have no default value. Deprecating a required field would silently break queries that depend on it.

Opt-In Features#

While @deprecated marks schema elements that are going away, @requiresOptIn marks schema elements that are not yet stable. This is useful for rolling out experimental features, expensive operations, or anything where consumers should make a deliberate choice to use it.

Schema elements marked with @requiresOptIn are hidden from introspection by default. Consumers opt in by specifying the feature name.

Enabling Opt-In Features#

Opt-in feature support is disabled by default. Enable it in your schema options:

C#
builder
    .AddGraphQL()
    .ModifyOptions(o => o.EnableOptInFeatures = true);

Marking Schema Elements as Opt-In#

Apply @requiresOptIn to output fields, input fields, arguments, enum values, and directive definitions. The directive is repeatable, so a single element can require multiple features.

Warning

Like @deprecated, you cannot apply @requiresOptIn to non-null arguments or input fields without a default value. Hiding a required field would break queries.

Introspection#

Consumers discover opt-in fields by passing the includeOptIn argument:

GraphQL
{
  __type(name: "Session") {
    fields(includeOptIn: ["experimentalInstantApi"]) {
      name
      requiresOptIn
    }
  }
}

The includeOptIn argument is available on fields, args, inputFields, enumValues, and directives in introspection queries. A directive definition exposes its own required features via __Directive.requiresOptIn, mirroring the requiresOptIn field on other introspection types.

To discover all opt-in features in the schema:

GraphQL
{
  __schema {
    optInFeatures
  }
}

Feature Stability#

You can declare the stability level of each opt-in feature. This helps consumers understand whether a feature is experimental, preview, or has some other status.

Consumers query feature stability through introspection:

GraphQL
{
  __schema {
    optInFeatureStability {
      feature
      stability
    }
  }
}

Next Steps#

Edit this page on GitHub
Last updated on by Tobias Tengler