100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
GraphQL

Query Arguments and Variables

Learn how GraphQL fields accept arguments to parameterize what they return, and how variables keep queries reusable, safe, and cacheable.

Queries & MutationsBeginner9 min readJul 10, 2026
Analogies

Arguments Let You Parameterize Any Field

Any field in a GraphQL schema, not just top-level query fields, can declare arguments the way a function declares parameters. A field like user(id: ID!) or posts(limit: Int, status: PostStatus) uses those arguments inside its resolver to decide exactly which data to fetch or filter, so the schema author controls precisely what each field can be parameterized by, and the client supplies concrete values inline in the query.

🏏

Cricket analogy: A field like playerStats(matchType: ODI) works like asking a stats engine for a specific player's One Day International numbers only, the way Cricinfo's Statsguru lets you filter Virat Kohli's record down to a single format instead of his whole career.

Variables Decouple Queries from Hard-Coded Values

Instead of hard-coding argument values directly into the query string, you declare named variables (prefixed with $) in the operation signature and reference them inside the selection set; the actual values are then supplied as a separate JSON object sent alongside the query in the request body. This means the query document itself never changes between requests — only the variables object does — which is essential for any client that runs the same query repeatedly with different inputs, such as a search box or a paginated list.

🏏

Cricket analogy: It's like a scoring app having one fixed template query GetPlayerStats($playerId: ID!) that stays identical every time, only swapping which player's ID gets passed in, the way a broadcast graphics template reuses the same layout for whichever batter is currently on strike.

Variable Types, Defaults, and Nullability

Each declared variable must have an explicit type in the operation signature, using the same type syntax as the schema: a bare type like String is nullable and optional, while an exclamation mark such as String! makes it non-null and required unless a default value is supplied with an equals sign, for example $limit: Int = 10. If a client sends null or omits a value for a non-null variable with no default, the server rejects the request during validation, before any resolver runs, which catches malformed requests early rather than letting them fail deep inside business logic.

🏏

Cricket analogy: Declaring $playerId: ID! is like a scorecard app refusing to even start rendering if no player is selected, catching the mistake immediately, the way a broadcast system errors out before air rather than showing a blank name mid-match.

graphql
query GetUserPosts($userId: ID!, $limit: Int = 10, $status: PostStatus) {
  user(id: $userId) {
    name
    posts(limit: $limit, status: $status) {
      id
      title
      publishedAt
    }
  }
}

# Variables sent separately in the request body:
# {
#   "userId": "u_9001",
#   "status": "PUBLISHED"
# }

Variables are transmitted as a separate JSON object alongside the query string in the POST body, typically under a "variables" key. This separation is exactly what makes the query string itself static and reusable — a client library like Apollo Client or Relay can cache and hash the query text once and simply swap variables per request.

Why Variables Matter for Caching and Security

Because the query text stays identical across calls, servers and CDNs can implement persisted queries — storing a hash of each known query so clients send only the hash plus variables, dramatically reducing request payload size and enabling automatic query allow-listing for security. Interpolating raw values directly into a query string instead of using variables reintroduces the same class of injection risk that parameterized SQL queries were invented to prevent, since a malicious or malformed string could alter the query's structure rather than just its data.

🏏

Cricket analogy: Using variables is like a stadium's ticketing API only ever accepting a fixed 'buy ticket' query hash plus a seat-number variable, rather than accepting raw freeform query text that a scalper could tamper with to grab unauthorized seats.

If you forget the non-null marker on a variable that your resolver logic actually requires — declaring $userId: ID instead of $userId: ID! — a client can send null, and the request will pass validation but then fail deep inside a resolver, or worse, silently return an empty or wrong result instead of a clear, early validation error.

  • Any field can declare arguments, defined per-field in the schema, similar to function parameters.
  • Variables ($name) let you keep the query text static and reusable while only the values change per request.
  • Variable types must be declared explicitly and can be non-null (Type!) or have a default value (Type = default).
  • Non-null variables without defaults are validated before execution, catching missing input early.
  • Static query text enables persisted queries, reducing payload size and enabling security allow-listing.
  • Never string-interpolate raw values into a query — always use variables to avoid injection-style risks.

Practice what you learned

Was this page helpful?

Topics covered

#GraphQL#GraphQLStudyNotes#WebDevelopment#QueryArgumentsAndVariables#Query#Arguments#Variables#Let#SQL#APIs#StudyNotes#SkillVeris