Docs
Launch GraphOS Studio

Directives

Configure GraphQL types, fields, and arguments


Looking for Apollo Federation s? See Federation-specific GraphQL directives.

A directive decorates part of a GraphQL or with additional configuration. Tools like Apollo Server (and Apollo Client) can read a GraphQL document's s and perform custom logic as appropriate.

s are preceded by the @ character, like so:

schema.graphql
type ExampleType {
oldField: String @deprecated(reason: "Use `newField`.")
newField: String
}

This example shows the @deprecated , which is a default directive (i.e., it's part of the GraphQL specification). It demonstrates the following about s:

  • s can take s of their own (reason in this case).
  • s appear after the declaration of what they decorate (the oldField in this case)

Valid locations

Each can only appear in certain locations within a GraphQL or . These locations are listed in the 's definition.

For example, here's the GraphQL spec's definition of the @deprecated :

directive @deprecated(
reason: String = "No longer supported"
) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | ENUM_VALUE

This indicates that @deprecated can decorate any of the four listed locations. Also note that its reason is optional and provides a default value. Usage examples of each location are provided below:

schema.graphql
# ARGUMENT_DEFINITION
# Note: @deprecated arguments _must_ be optional.
directive @withDeprecatedArgs(
deprecatedArg: String @deprecated(reason: "Use `newArg`")
newArg: String
) on FIELD
type MyType {
# ARGUMENT_DEFINITION (alternate example on a field's args)
fieldWithDeprecatedArgs(name: String @deprecated): String
# FIELD_DEFINITION
deprecatedField: String @deprecated
}
enum MyEnum {
# ENUM_VALUE
OLD_VALUE @deprecated(reason: "Use `NEW_VALUE`.")
NEW_VALUE
}
input SomeInputType {
nonDeprecated: String
# INPUT_FIELD_DEFINITION
deprecated: String @deprecated
}

If @deprecated appears elsewhere in a GraphQL document, it produces an error.

If you create a custom directive, you need to define it (and its valid locations) in your . You don't need to define default directives like @deprecated.

Schema directives vs. operation directives

Usually, a given appears exclusively in GraphQL s or exclusively in GraphQL s (rarely both, although the spec allows this).

For example, among the default directives, @deprecated is a -exclusive and @skip and @include are -exclusive s.

The GraphQL spec lists all possible locations. locations are listed under TypeSystemDirectiveLocation, and locations are listed under ExecutableDirectiveLocation.

Default directives

The GraphQL specification defines the following default s:

DirectiveDescription
@deprecated(reason: String)Marks the schema definition of a field or enum value as deprecated with an optional reason.
@skip(if: Boolean!)If true, the decorated field or fragment in an operation is not resolved by the GraphQL server.
@include(if: Boolean!)If false, the decorated field or fragment in an operation is not resolved by the GraphQL server.

Custom directives

⚠️ Apollo Server does not provide built-in support for custom s that transform a .

Your can define custom s that can then decorate other parts of your schema:

# Definition
directive @uppercase on FIELD_DEFINITION
type Query {
# Usage
hello: String @uppercase
}

If you want to define a custom to transform your executable 's behavior before providing that schema to Apollo Server, we recommend using the @graphql-tools library. See our example of using a custom directive to transform a schema.

In subgraphs

Before you use custom s in a federated graph, make sure to consider the following:

  • If multiple s can resolve a particular , each subgraph should almost always apply the exact same set of custom s (with the exact same definition) to that field. Otherwise, the behavior of that field might vary depending on which resolves it.
  • Because s are specific to individual s, it's technically valid for different subgraphs to define the same with different logic. As stated in the previous point, if a custom is used in multiple s to resolve a particular , you should define the same directive with the same logic across subgraphs. Composition does not detect or warn about such inconsistencies.
  • The composition process treats executable (client-side) and type system (server-side) directives differently:
    • An executable is composed into the if:
      • All s define the identically
      • The is not included in any @composeDirective s
    • Type system s are not composed into the , but they can provide information to the via the @composeDirective .

Transformer functions

As our example shows, in Apollo Server 3 and 4 you can define a transformer function for each of your 's custom s.

To apply transformer functions to your executable , you first generate the with buildSubgraphSchema as usual:

let subgraphSchema = buildSubgraphSchema({ typeDefs, resolvers });

But instead of passing the result directly to the ApolloServer constructor, you first apply all of your transformer functions to it:

// Transformer function for an @upper directive
subgraphSchema = upperDirectiveTransformer(subgraphSchema, 'upper');

After applying all transformer functions, you provide your final to the ApolloServer constructor as usual:

const server = new ApolloServer({
schema: subgraphSchema,
// ...other options...
});
Previous
Custom scalars
Next
Resolvers
Edit on GitHubEditForumsDiscord