Skip to content

Indicate that field arguments should always be preferred over directives #4417

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 29, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion website/pages/docs/using-directives.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,10 @@ You can apply directives to:

- Fields
- Fragment spreads
- Named fragments
- Inline fragments
- Operations (query, mutation or subscription)
- Variable definitions

The following examples show how to apply directives:

Expand Down Expand Up @@ -253,6 +256,49 @@ Some common use cases for custom directives include:
- **Observability**: `@log`, `@tag(name: "important")`, or `@metrics(id: "xyz")`
- **Execution control**: Mask or transform fields at runtime with schema visitors

## When to avoid custom directives

Custom directives should not be used where an argument could achieve the same
goal. Custom directives in GraphQL requests complicate caching (particularly
normalized caches) and are less well understood by tooling such as GraphQL; by
using arguments instead we maximize compatibility and consistency. For example,
our `@uppercase` directive would fit naturally as a field argument:

```js
import {
graphql,
buildSchema,
} from 'graphql';

const schema = buildSchema(`
enum Format {
VERBATIM
UPPERCASE
}
type Query {
greeting(format: Format! = VERBATIM): String
}
`);

const rootValue = {
greeting: (source, args) => {
const result = 'Hello, world';

if (args.format === "UPPERCASE") {
return result.toUpperCase();
}

return result;
},
};

const query = `
query {
greeting(format: UPPERCASE)
}
`;


## Best practices

When working with custom directives in GraphQL.js, keep the following best practices in mind:
Expand All @@ -261,6 +307,7 @@ When working with custom directives in GraphQL.js, keep the following best pract
manually.
- Weigh schema-driven logic against resolver logic. Directives can make queries more expressive, but they
may also hide behavior from developers reading the schema or resolvers.
- Always prefer field arguments over directives where possible.
- Keep directive behavior transparent and debuggable. Since directives are invisible at runtime unless
logged or documented, try to avoid magic behavior.
- Use directives when they offer real value. Avoid overusing directives to replace things that could be
Expand All @@ -272,4 +319,4 @@ writing custom validation rules to enforce correct usage.

- [GraphQL Specification: Directives](https://spec.graphql.org/draft/#sec-Language.Directives)
- The Guild's guide on [Schema Directives](https://the-guild.dev/graphql/tools/docs/schema-directives)
- Apollo Server's guide on [Directives](https://www.apollographql.com/docs/apollo-server/schema/directives)
- Apollo Server's guide on [Directives](https://www.apollographql.com/docs/apollo-server/schema/directives)
Loading