🎉 Explore GraphQLConf 2026 • May 19-21 • Fremont, CA • View the schedule
DocumentationDirectives on Directives

Directives on Directive Definitions

GraphQL.js supports directives applied to directive definitions, directive extensions, and directive deprecation metadata through experimental APIs.

When the experiment is enabled, GraphQL directives can be applied to directive definitions. This is the SDL shape introduced by the directives-on-directives proposal:

directive @tag(name: String!) on DIRECTIVE_DEFINITION
 
directive @cacheControl(maxAge: Int) @tag(name: "runtime") on FIELD_DEFINITION

The directive location is DIRECTIVE_DEFINITION.

import { DirectiveLocation } from 'graphql';
 
DirectiveLocation.DIRECTIVE_DEFINITION;

Parser surface

Directive definition directives are represented on the AST:

  • DirectiveDefinitionNode.directives
  • DirectiveExtensionNode.directives
  • Kind.DIRECTIVE_EXTENSION

Parsing this syntax is controlled by experimentalDirectivesOnDirectiveDefinitions.

import { parse } from 'graphql';
 
const document = parse(source, {
  experimentalDirectivesOnDirectiveDefinitions: true,
});

Directive extensions use the same option:

extend directive @cacheControl @tag(name: "performance")

Runtime schema surface

GraphQL.js does not add a generic GraphQLDirective.directives property. The applied directives remain available through the AST nodes:

  • GraphQLDirective.astNode?.directives
  • GraphQLDirective.extensionASTNodes

GraphQL.js does derive directive deprecation metadata from those AST nodes. GraphQLDirective includes:

  • deprecationReason
  • extensionASTNodes
const directive = schema.getDirective('cacheControl');
 
directive.deprecationReason;
directive.astNode?.directives;
directive.extensionASTNodes;

Deprecating custom directives

@deprecated can be used on directive definitions. The built-in GraphQLDeprecatedDirective includes DIRECTIVE_DEFINITION in its locations.

directive @oldAuth @deprecated(reason: "Use @auth instead") on FIELD_DEFINITION

The introspection type __Directive includes:

  • isDeprecated
  • deprecationReason

__Schema.directives accepts includeDeprecated: Boolean! = false when directive deprecation support is present.

query DeprecatedDirectives {
  __schema {
    directives(includeDeprecated: true) {
      name
      isDeprecated
      deprecationReason
    }
  }
}

Directive extensions

Directive extensions can attach deprecation metadata to a directive defined in another document:

directive @oldAuth on FIELD_DEFINITION
 
extend directive @oldAuth @deprecated(reason: "Use @auth instead")

When a schema is extended, GraphQL.js preserves directive extension AST nodes on GraphQLDirective.extensionASTNodes and uses them when computing deprecationReason.

Validation

KnownDirectivesRule understands DIRECTIVE_DEFINITION, so a directive applied to a directive definition must itself be declared for that location.

UniqueDirectivesPerLocationRule also treats a directive definition and its extensions as one directive location for non-repeatable directive uniqueness.