GraphQL Variables Guide
A practical guide to GraphQL variables covering syntax, type declarations, default values, input objects, lists, nullability, mutations, and debugging.
GraphQL variables allow clients to pass dynamic values into queries and mutations without embedding those values directly into the operation document. They are especially useful for values that come from user input, application state, URL parameters, forms, filters, pagination controls, and API requests.
Instead of constructing a new GraphQL query every time a value changes, the client can keep the operation document unchanged and provide different variable values with each request. GraphQL then validates those values against the variable types declared by the operation.
This guide explains GraphQL variable syntax, variable definitions, scalar types, non-null variables, default values, lists, input objects, queries, mutations, JSON variables, common errors, and practical best practices.
What Are GraphQL Variables?
A GraphQL variable is a named value supplied separately from a GraphQL operation. Variables are declared at the beginning of an operation and referenced inside the query or mutation with a dollar sign.
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
}
}In this example, $id is the variable. The declaration says that the variable has the ID! type. The same variable is then passed to the user field as its id argument.
The actual value is provided separately as JSON.
{
"id": "42"
}Why Use GraphQL Variables?
Variables separate the GraphQL operation itself from the values used by that operation. This is useful because the same operation can be executed repeatedly with different values.
query SearchProducts($term: String!) {
products(search: $term) {
id
name
price
}
}{
"term": "keyboard"
}The operation does not need to be rewritten when the search term changes. The client can send another variables object containing a different value.
- Keep operation documents reusable.
- Avoid embedding dynamic values directly into GraphQL documents.
- Allow GraphQL to validate variable values against declared types.
- Pass structured data such as input objects and lists.
- Work naturally with queries and mutations.
- Make frontend forms and API calls easier to integrate.
GraphQL Variable Syntax
A variable definition uses the variable name followed by its GraphQL type.
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}The general structure is a dollar sign, variable name, colon, and type.
($variableName: VariableType)The variable definition appears after the operation name. If an operation has several variables, they are separated by commas or whitespace.
query Search(
$term: String!
$limit: Int
$active: Boolean
) {
products(
search: $term
limit: $limit
active: $active
) {
id
name
}
}Variable Definitions vs Variable Values
GraphQL separates the declaration of a variable from the value supplied with the request. The GraphQL document contains the variable definition, while the request's variables object contains the actual value.
query GetProduct($id: ID!) {
product(id: $id) {
id
name
price
}
}{
"id": "100"
}Here, ID! describes what type of value the operation expects. The JSON object provides the concrete value used during execution.
GraphQL Variable Types
Variables use GraphQL input types. Common built-in scalar types include String, Int, Float, Boolean, and ID.
| Type | Purpose | Example value |
|---|---|---|
| String | Text | "hello" |
| Int | Integer number | 42 |
| Float | Decimal number | 19.95 |
| Boolean | True or false | true |
| ID | Unique identifier | "user-42" |
A schema can also define custom scalar types and input object types. Variables must use types that are valid input types in the schema.
String Variables
String variables are useful for names, search terms, messages, descriptions, and other textual values.
query SearchUsers($name: String!) {
users(name: $name) {
id
name
}
}{
"name": "Anna"
}Integer Variables
Int variables represent GraphQL integer values and are commonly used for limits, offsets, counts, and numeric identifiers when the schema expects Int.
query GetProducts($limit: Int!) {
products(limit: $limit) {
id
name
}
}{
"limit": 20
}Float Variables
Float variables are used when the schema expects a floating-point value, such as a price, measurement, or calculated numeric value.
query ProductsAbovePrice($price: Float!) {
products(minPrice: $price) {
id
name
price
}
}{
"price": 99.5
}Boolean Variables
Boolean variables accept true or false values and are useful for filters, feature flags, visibility settings, and other binary conditions.
query GetProducts($available: Boolean!) {
products(available: $available) {
id
name
}
}{
"available": true
}ID Variables
The ID scalar represents a unique identifier. GraphQL allows ID values to be serialized as strings, and GraphQL implementations can also accept integer input values where the specification permits ID input coercion.
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}{
"id": "42"
}Nullable GraphQL Variables
A variable without an exclamation mark is nullable. For example, String allows a string value or null, subject to the rules of the operation and schema.
query SearchProducts($term: String) {
products(search: $term) {
id
name
}
}If the variable is omitted or supplied as null, the behavior depends on how the corresponding field argument and resolver are defined.
Non-Null GraphQL Variables
Adding ! to a variable type makes the variable non-null. The client must provide a non-null value unless a default value changes the variable's requirements.
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}The variable cannot be explicitly set to null when its type is ID!. If the required variable is missing, GraphQL validation or execution will report an error.
GraphQL Lists as Variable Types
GraphQL uses square brackets to represent list input types. For example, [ID!]! means a non-null list containing non-null ID values.
query GetProducts($ids: [ID!]!) {
products(ids: $ids) {
id
name
}
}{
"ids": ["10", "20", "30"]
}The placement of ! matters. [ID!]! means the list itself cannot be null and its individual elements cannot be null.
| Type | Meaning |
|---|---|
| [ID] | Nullable list of nullable IDs |
| [ID!] | Nullable list of non-null IDs |
| [ID]! | Non-null list of nullable IDs |
| [ID!]! | Non-null list of non-null IDs |
GraphQL Input Object Variables
Input objects allow clients to pass structured data as one variable. They are especially common in mutations, where an operation may require several related values.
mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) {
id
name
email
}
}{
"input": {
"name": "Anna",
"email": "[email protected]"
}
}CreateUserInput is an input object type defined by the GraphQL schema. Its fields and their types determine which values can be supplied.
Nested Input Objects
Input objects can contain nested input objects when the schema defines them that way.
mutation CreateOrder($input: CreateOrderInput!) {
createOrder(input: $input) {
id
total
}
}{
"input": {
"customer": {
"id": "42"
},
"shipping": {
"city": "Berlin",
"postalCode": "10115"
}
}
}The exact structure is determined by the schema. A client cannot arbitrarily add fields to an input object if those fields are not defined by its input type.
Default Values for GraphQL Variables
A variable definition can include a default value. The default is used when the client does not provide a value for that variable.
query GetProducts($limit: Int = 20) {
products(limit: $limit) {
id
name
}
}If the variables object does not provide limit, the operation can use 20. If the client supplies another value, that supplied value is used instead, provided it satisfies the variable's type and the field's requirements.
{
"limit": 50
}Variables in GraphQL Queries
Variables are particularly useful for queries that depend on changing filters, IDs, pagination values, or search terms.
query GetPosts(
$category: String
$limit: Int = 10
$offset: Int = 0
) {
posts(
category: $category
limit: $limit
offset: $offset
) {
id
title
}
}{
"category": "graphql",
"limit": 20,
"offset": 0
}The same query document can be reused for another category or pagination position simply by changing the variables object.
Variables in GraphQL Mutations
Mutation variables are commonly used when submitting form data or other user-generated input.
mutation UpdateUser(
$id: ID!
$name: String!
$active: Boolean!
) {
updateUser(
id: $id
name: $name
active: $active
) {
id
name
active
}
}{
"id": "42",
"name": "Anna Smith",
"active": true
}For larger mutations, an input object often provides a cleaner interface.
mutation UpdateUser($input: UpdateUserInput!) {
updateUser(input: $input) {
id
name
active
}
}GraphQL Variables and JSON
Variables are commonly transported as a JSON object alongside the GraphQL document. The variable names in JSON correspond to the variable names declared in the operation.
query GetProduct($id: ID!, $includeReviews: Boolean!) {
product(id: $id) {
id
name
reviews @include(if: $includeReviews) {
id
rating
}
}
}{
"id": "42",
"includeReviews": true
}The JSON object is not itself a GraphQL document. It contains values that are supplied to the variables declared by the GraphQL operation.
Variable Names Must Match
The variable name in the request must correspond to a variable declared by the operation.
query GetUser($userId: ID!) {
user(id: $userId) {
id
name
}
}{
"id": "42"
}This request uses id instead of userId, so it does not provide the declared $userId variable. The correct variables object is:
{
"userId": "42"
}Variables Are Not String Interpolation
A common mistake is treating GraphQL variables as string interpolation. Variables are not inserted into a GraphQL document by manually replacing placeholders. They are values supplied separately to the GraphQL execution process.
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}The client should provide the variables through the GraphQL client's variables mechanism rather than constructing the query by concatenating strings.
Variable Compatibility with Field Arguments
A variable's type must be compatible with the argument type expected by the field where the variable is used. Declaring a variable with the wrong type can cause the operation to fail validation before execution.
query GetUser($id: String!) {
user(id: $id) {
id
name
}
}If the user field expects an ID! argument, using String! may not be valid even though both types can represent textual-looking values. GraphQL type compatibility is determined by the schema and input type rules, not simply by the runtime appearance of the value.
Variable Nullability and Argument Nullability
Variable and argument nullability interact. If a field argument requires a non-null value, the variable supplied to that argument generally needs to guarantee a compatible non-null value.
query GetUser($id: ID!) {
user(id: $id) {
id
}
}Using ID! makes it clear that the operation expects a non-null ID. Understanding where ! appears is important when working with variables, lists, and input objects.
Variables with Enum Types
GraphQL schemas can define enum types that restrict a value to a predefined set of names. Variables can use those enum types just like scalar types.
query GetProducts($sort: ProductSort!) {
products(sort: $sort) {
id
name
}
}{
"sort": "PRICE_ASC"
}Enum values are GraphQL enum values, not arbitrary strings. The value must match one of the enum members defined by the schema.
Variables with Custom Scalars
GraphQL schemas can define custom scalar types for values such as dates, timestamps, URLs, UUIDs, or other application-specific formats.
query GetEvents($date: DateTime!) {
events(after: $date) {
id
title
}
}{
"date": "2026-09-03T12:00:00Z"
}The serialization and validation rules for a custom scalar are determined by the GraphQL server implementation. The client should follow the format documented by the API.
Variables and Directives
Variables can be passed to GraphQL directives when the directive accepts arguments of compatible types. Built-in directives such as @include and @skip are common examples.
query GetUser(
$id: ID!
$includeEmail: Boolean!
) {
user(id: $id) {
id
name
email @include(if: $includeEmail)
}
}{
"id": "42",
"includeEmail": true
}Multiple Variables in One Operation
An operation can declare as many variables as its schema and application requirements need. Each variable has its own type and can be used in one or more compatible positions.
query SearchProducts(
$term: String!
$categoryId: ID
$minPrice: Float
$limit: Int = 20
) {
products(
search: $term
categoryId: $categoryId
minPrice: $minPrice
limit: $limit
) {
id
name
price
}
}{
"term": "keyboard",
"categoryId": "5",
"minPrice": 50,
"limit": 10
}Variables Used Multiple Times
A variable can be used more than once when every usage is compatible with its declared type.
query Search(
$term: String!
) {
products(search: $term) {
id
name
}
categories(search: $term) {
id
name
}
}Using one variable for related arguments can keep an operation concise and ensures that those arguments receive the same input value.
Unused GraphQL Variables
A variable declared by an operation should be used by that operation. Declaring unnecessary variables can cause validation errors according to GraphQL's operation validation rules.
query GetUser(
$id: ID!
$name: String
) {
user(id: $id) {
id
name
}
}In this example, $name is declared but not used. Removing unused variables makes the operation cleaner and avoids validation problems.
Common GraphQL Variable Errors
- Required variable was not provided.
- A variable was supplied with null even though its type is non-null.
- The variable type does not match the expected argument type.
- The variables JSON uses the wrong variable name.
- An input object contains fields not defined by its input type.
- A list contains values that do not match the declared element type.
- An enum variable uses a value that is not defined by the enum.
- A variable is declared but never used.
- A variable is used in a location where its type is incompatible.
- A custom scalar receives a value in an unsupported format.
How to Debug GraphQL Variable Errors
When a GraphQL operation fails because of variables, inspect the operation and variables object separately. This makes it easier to determine whether the problem is the declaration, the supplied value, or the way the variable is used.
- Check every variable declaration in the operation.
- Verify the variable name in the JSON object.
- Compare the declared type with the schema argument type.
- Check whether required variables are present.
- Look for null values assigned to non-null variables.
- Verify list structure and element types.
- Check input object field names and nested structures.
- Verify enum values against the schema.
- Check custom scalar formats.
- Inspect the GraphQL errors returned by the server.
query GetProduct($id: ID!) {
product(id: $id) {
id
name
price
}
}{
"id": "42"
}Starting with a small operation and a simple variables object is often easier than debugging a large query with many nested inputs and directives.
GraphQL Variables in JavaScript
GraphQL clients commonly represent variables as a JavaScript object. For example, a request library can send the GraphQL document together with the variables object.
const variables = {
id: "42",
includeReviews: true,
};The exact request API depends on the GraphQL client or HTTP library. The important part is that the variable names and values match the GraphQL operation's declarations.
GraphQL Variables in TypeScript
TypeScript applications can define types for variables to catch some mistakes before a request is sent. Many GraphQL development workflows can also generate TypeScript types from a GraphQL schema and operation documents.
type GetUserVariables = {
id: string;
};
const variables: GetUserVariables = {
id: "42",
};Generated types can provide stronger synchronization between GraphQL operations and application code, especially in larger projects.
GraphQL Variables vs Hardcoded Values
| Approach | Example | Typical use |
|---|---|---|
| Hardcoded value | user(id: "42") | Fixed example or static request |
| Variable | user(id: $id) | Dynamic application input |
Hardcoded values are perfectly valid when a value is genuinely static. Variables become more useful when the same operation needs to work with changing input.
Best Practices for GraphQL Variables
- Use variables for dynamic values instead of constructing GraphQL documents through string concatenation.
- Choose the variable type that matches the schema argument type.
- Use non-null types when the operation genuinely requires a value.
- Use input objects for complex mutation data when the schema provides them.
- Keep variable names descriptive and consistent with their purpose.
- Avoid declaring variables that the operation does not use.
- Validate variable values before sending requests when appropriate.
- Keep variables separate from the GraphQL operation document.
- Use generated GraphQL types in TypeScript projects when practical.
- Inspect both the GraphQL document and variables object when debugging.
- Do not log sensitive variable values unnecessarily.
Frequently Asked Questions
What are variables in GraphQL?
GraphQL variables are named values supplied separately from a query or mutation. They allow an operation to receive dynamic input without embedding that input directly into the GraphQL document.
How do you define a variable in GraphQL?
A variable is defined after the operation name using a dollar sign, a variable name, and an input type, such as $id: ID!.
Where are GraphQL variable values provided?
Variable values are commonly provided in a separate JSON object called the variables object. Its property names correspond to the variables declared by the GraphQL operation.
What does ! mean in a GraphQL variable type?
The exclamation mark makes the type non-null. A variable such as $id: ID! must receive a non-null value unless the operation's default-value rules provide an applicable alternative.
Can GraphQL variables contain objects?
Yes. Variables can use schema-defined input object types, including nested input objects and lists. This is especially common with complex mutations.
Can GraphQL variables be used in mutations?
Yes. Variables are widely used with mutations to pass form data, identifiers, configuration values, and structured input objects.
Why is my GraphQL variable not working?
Common causes include a missing required variable, a variable name mismatch, an incompatible type, an invalid input object, a null value for a non-null type, an invalid enum value, or an incorrectly formatted custom scalar.
Helpful GraphQL and JSON Tools
Several developer tools can make working with GraphQL variables easier. Variable formatters can help keep complex variables JSON readable, while query formatters improve the structure of GraphQL documents. Endpoint testers can send complete GraphQL requests for debugging, and JSON formatters and validators can help verify the variables object before it is submitted to an API.
Conclusion
GraphQL variables provide a clean way to separate an operation from the dynamic values it receives. They work with queries, mutations, directives, lists, input objects, enums, custom scalars, and default values.
The basic pattern is simple: declare each variable with a compatible GraphQL input type, reference it with a dollar sign inside the operation, and provide its value separately in the variables object. Understanding nullability, list syntax, input objects, and type compatibility is especially important when working with larger GraphQL APIs.