---
# System prepended metadata

title: Directives
tags: [concept cards]

---

# Directives

A GraphQL client request specifies operations such as queries and the fields that you want to query. Each field in a query is then resolved by a resolver function that runs on the GraphQL server. However, there are situations when you want the resolver function to handle the same field differently. For instance, let's say you query a field which is resolved by fetching a record from the database. This works fine, but you might want the resolver to return a dummy object for the same field on a test environment. For such alternate execution scenarios, GraphQL provides a feature known as directives. 

![Directive](https://hackmd.io/_uploads/SJrxWm1C3.png)


The [GraphQL specification](https://spec.graphql.org/draft/) specifies directives as a means for the client to provide additional input. As illustrated in the figure above these directives will be applied by a resolver function and can dynamically affect the resolver function's behavior.  Directives may be provided by the client or defined in the schema and are usually preceded by a @ symbol. 

```graphql
directive @mock on OBJECT

type Player @mock {
    firstName: String!
    lastName: String!
    score: Int!
}
```

In the above example, a directive called @mock is defined on an object. This directive is used on the Player object to return mock details of a player during execution. 


## Built-in directives
Built-in directives such as @skip, @include, @deprecated, and @specifiedBy are defined in the GraphQL specification, and all GraphQL implementations must implement them. 
- **@skip** can be used to conditionally skip a field in the response based on the value of a Boolean argument.
- **@include** can be used to conditionally include a field in the response based on the value of a Boolean variable.
- **@deprecated** marks a field or an entire object type as deprecated and a reason for the deprecation.
- **@specifiedBy** applied to a custom scalar. It takes a URL argument that specifies the location of a formal specification of the scalar.

The [Directives section of the GraphQL specification](https://spec.graphql.org/draft/#sec-Type-System.Directives) describes each of the built-in directives in detail.

### Future of built-in directives
Before any additions to the GraphQL specification, there is an RFC process for each proposal. Directives @defer and @stream are in [RFC](https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.md) phase and could soon be part of the official specification. Though @defer and @stream are not part of the official GraphQL specification yet, they are supported by popular GraphQL servers, including the Graphql.js reference implementation. Let's take a closer look at these.
#### @defer and @stream
GraphQL operates in a request-response fashion. You specify all the fields you want in a request and wait for the complete response. If a field in the query takes longer to be resolved than the others, it may hold up the entire response thus leading to increased latency. 

Let's discuss this with the help of an example of the Netflix home page. The page has a listing of all your favorite shows and movies. A GraphQL request for the home page may include fields such as show title, description and the thumbnail video for that show. It definitely takes longer to fetch the thumbnail video as compared to the title. But you would still have to wait for the entire response so that you can see the list of shows. As a workaround, you can choose to split the query into two queries but that would only increase the load on the server and costs too. 

It would be helpful if you could specify fields that you want to defer the response for, in this case, the thumbnail video. That way, you could atleast view show titles on the home page, while the videos load. This is made possible by the @defer directive. The @defer directive allows you to return the non-deferred essential fields of the query first and the non-essential data incrementally across multiple payloads. 

Here's a query that uses @defer:

```graphql
query {
 shows {
  title,
  ...VideoFragment @defer(label: "videoDefer"),
  description,
 }
}
fragment VideoFragment on Show {
 thumbnailVideo,
 previewVideo
}
```
The @defer directive is applied to the VideoFragment which defers the response for the thumbnail and preview videos to a subsequent payload. The first payload would contain the non-deferred fields such as title and description, thus fulfilling the requirement.

Now, let's say you select a particular show. It displays a list of episodes for the show along with the title and description. But what if the show is a soap opera that has a hundred episodes? This long list of episodes will hold up the entire response. As a possible solution, you could defer the list of episodes altogether. But you would at least like to see a list of a few initial episodes before scrolling down the entire list. The @stream directive can help achieve this goal.
You can apply the @stream directive to lists, in this case, a list of episodes. The directive also takes in an initialCount argument which ensures that at least an initial list of episodes can be returned in the first payload.

```graphql!
query {
 show(id: "lGcvdGqeOmE=") {
  title,
  ...VideoFragment @defer(label: "videoDefer"),
  description,
  episodes @stream(initialCount: 2, label: "episodesStream"){
    title,
  }
 }
}
fragment VideoFragment on Show {
 previewVideo
}
```
The query along with the show title, description and deferred video, also requests for the list of episodes. Since the initialCount is two, only two episodes will be returned with the non-deferred fields in the first payload. Both the @defer and @stream directives take a unique label argument that helps patch the responses to the requested fields.

#### Response #Payload 1
```graphql
{
  "data": {
    "show": {
      "title": "You",
      "description": "The story of a dangerous, intensely obsessive young man.",
      "episodes": [
      {"title": "Pilot"},
      {"title": "Maybe"}
      ]
    }
  },
  "hasNext": true
}

```
Since hasNext is true, there is a second payload that returns the deferred video.
#### Response #Payload 2
```graphql
{
  "label": "videoDefer",
  "path": ["show"],
  "data": {
    "video": <binary-video-content>
  },
  "hasNext": true
}
```
This payload is patched to the show via the label videoDefer and path. Since hasNext for this payload is also true, there is another subsequent payload that returns the remaining list of episodes.
#### Response #Payload 3

```graphql
{
  "label": "episodesStream",
  "path": ["show", "episodes", 2],
  "data": {
      "title": "The Captain"    
  }
  "hasNext": false
}
```
There isn't any subsequent payload after the third one since hasNext equals false. 

## Custom Directives
A few built-in directives are defined in the specification, but they may not be enough for all of your potential use cases. In such situations, you can use custom directives. Custom directives are user-defined directives in GraphQL that can be used to extend the functionality of the GraphQL schema language beyond the built-in directives. 

Custom directives are used by tooling providers to provide additional features such as authorization, caching, and schema stitching. You may, however, define your own custom directives independent of what the tooling offers.

## Key takeaways
Here's a quick recap of all we discussed:
- Directives are one of the most powerful features of GraphQL which are used to annotate parts of a GraphQL request or schema with metadata that may be used to modify how a field is resolved by the resolver.
- The GraphQL specification describes four built-in directives that implementors must define. These are @skip, @include, @deprecated and @specifiedBy.
- In addition to built-in directives, implementations define some custom directives that allow you to enable features.
- @defer and @stream are defined in the [RFC](https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.md), not yet part of the official specification, but supported by popular implementations.
- Numerous other use cases exist for directives, so you can define your custom directives to fulfill them too.
