Conditionally Include or Omit GraphQL Fields with @skip and @include
Control which fields a GraphQL query returns using Boolean variables and the @skip and @include directives, without changing the query structure.
17 Jan 2026, 03:05 UTC

Useful takeaway
If a GraphQL query sometimes returns fields your client does not need, you can turn those fields on or off at request time using the @skip and @include directives. Both directives accept a Boolean argument. When the condition is true, @skip removes the field from the response and @include keeps it; when false, the behavior reverses. This keeps a single query shape while avoiding over-fetching.
How the directives work
@skip and @include are standard GraphQL directives. A directive is an annotation attached to a part of a query document that tells the server how to treat that part. These two directives can be placed on fields, fragment spreads, and inline fragments. They cannot be placed on operation names, arguments, or the query root.
The server evaluates the Boolean variable at execution time. If the directive condition is not met, the field is omitted from the result. The query text stays the same; only the variables change.
Worked example
Assume a GraphQL server exposes this schema:
type Query {
user(id: ID!): User
}
type User {
id: ID!
name: String!
age: Int
}
The following query asks for a user and conditionally omits the age field:
query GetUser($showAge: Boolean!) {
user(id: "1") {
id
name
age @skip(if: $showAge)
}
}
Run this query from a GraphQL client, such as Apollo Client, Relay, or an HTTP client sending a POST request to the server's GraphQL endpoint. No special server permissions are required beyond the normal permission to execute the query.
Variable: { "showAge": false }
Expected response shape:
{
"data": {
"user": {
"id": "1",
"name": "Ada",
"age": 29
}
}
}
Variable: { "showAge": true }
Expected response shape:
{
"data": {
"user": {
"id": "1",
"name": "Ada"
}
}
}
These are illustrative response shapes, not captured server output. Verify against your own server.
Verify server support
Before relying on the directives, confirm the server advertises them. Run an introspection query against the endpoint:
query {
__schema {
directives {
name
locations
}
}
}
Look for skip and include in the directives list, with locations including FIELD, FRAGMENT_SPREAD, and INLINE_FRAGMENT. If either directive is missing, the server or GraphQL library version does not support conditional field inclusion this way.
Limits and common mistakes
- Directive placement.
@skipand@includeonly apply to fields, fragment spreads, and inline fragments. Putting one on an operation name or an argument causes a validation error before execution. - Resolver execution. Omitting a field from the response does not necessarily prevent the server from resolving it. Resolver logic, logging, and authorization checks may still run. Do not use these directives to hide sensitive data for security.
- Variables are required. If the client omits the Boolean variable, the server returns a validation or runtime error. Always supply the variable with the correct type.
- Caching. Different variable values produce different response shapes. Client caches that key responses by query text alone may return stale or incomplete results. Include variables in the cache key where supported.
- Older libraries. Some older GraphQL server implementations predate standardized directive support. Check your server version if introspection does not list the directives.
Practical check
- Run the query with
showAgeset tofalseand confirmageappears in the JSON response. - Run the same query with
showAgeset totrueand confirmageis absent whileidandnameremain. - Run the introspection query above and confirm
skipandincludeappear in__schema.directives.
If all three checks pass, conditional field inclusion is working on your server. If a field remains present when it should be skipped, inspect the client variable payload and the server's directive handling before assuming the query is wrong.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.