Arguments and variables

GraphQL · Essentials · 10 min

Variables make operations reusable, cacheable and safe from injection.

Any field can declare arguments, e.g. book(id: ID!) or books(genre: Genre, first: Int = 10). Arguments can have default values in the schema.

Hard-coding values into the query string works for exploration, but real clients use variables: the operation declares typed placeholders, and values travel separately as JSON.

query Book($id: ID!, $withReviews: Boolean = false) {
  book(id: $id) { title }
}

The HTTP body then carries {"query": "...", "variables": {"id": "b1"}}.

Why this matters:

  • The query text stays constant, so it can be cached, persisted and logged by name.
  • Values are validated against declared types; you never build query strings with string concatenation, which avoids injection bugs.
  • Variable types must be compatible with where they are used: $id: ID (nullable) cannot be passed to an ID! argument unless it has a default.

Complex arguments use input types, declared with input instead of type. Input types may only contain scalars, enums and other input types, never output object types.

Directives @include(if: $flag) and @skip(if: $flag) let variables toggle parts of a selection.

Example

import { buildSchema, graphql } from "graphql";

const schema = buildSchema(`
  type Query { greet(name: String!, excited: Boolean = false): String! }
`);
const rootValue = {
  greet: ({ name, excited }) => `Hello, ${name}${excited ? "!" : "."}`,
};
const source = `query Greet($who: String!, $loud: Boolean) {
  greet(name: $who, excited: $loud)
}`;
const res = await graphql({
  schema, rootValue, source,
  variableValues: { who: "Ann", loud: true },
});
console.log(JSON.stringify(res.data)); // {"greet":"Hello, Ann!"}

Remember

  • Declare $vars with types in the operation, send values as JSON
  • Never build query strings by concatenating user input
  • Complex arguments use input types
  • @include / @skip toggle fields from variables

Watch out for

  • Passing a nullable variable to a non-null argument without a default; validation rejects it.

Check yourself

  1. Why should clients send values as variables rather than inlining them?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: graphql.org/learn/queries/#variables