Q&A
What are the different ways to pass an argument in GraphQL?
Overview
GraphQL fields can accept arguments to filter, paginate, or shape data, and mutations use arguments to carry the data to change. There isn't one way to pass them - the choice affects reusability, validation, and security. Knowing all the mechanisms (and when to use each) is the substance of this question.
graph TD
A[Passing arguments in GraphQL] --> B[Inline literals: quick, hard-codes values]
A --> C["Variables: $var - reusable, typed, safe"]
A --> D[Input types: bundle many args into one object]
A --> E[Default values: arg defaults in the schema]
A --> F[Nested-field arguments]
style C fill:#1e1b4b,color:#fff
style D fill:#1e1b4b,color:#fff
1. Inline Arguments (literals)
Write the value directly in the query - fine for exploration, not for apps:
query {
user(id: "42") {
name
posts(first: 5) { title }
}
}
Downsides: values are baked into the query string; you'd rebuild the string per request, and dynamic user input concatenated into queries is error-prone.
2. Variables (the recommended way)
Declare typed variables with $, then supply their values separately (as JSON). This makes queries reusable and keeps user input out of the query text:
query GetUser($id: ID!, $count: Int = 5) {
user(id: $id) {
name
posts(first: $count) { title }
}
}
// variables sent alongside the query
{ "id": "42", "count": 10 }
$id: ID!- required (the!).$count: Int = 5- a default value if not provided. Variables are typed and validated by the server, and the same query document works for any inputs.
3. Input Types (bundling many arguments)
For mutations (or queries) with many arguments, define an input type so you pass one structured object instead of a long argument list:
# schema
input CreateUserInput {
name: String!
email: String!
age: Int
}
type Mutation {
createUser(input: CreateUserInput!): User
}
# query
mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) { id name }
}
{ "input": { "name": "Ada", "email": "ada@example.com", "age": 30 } }
Input types keep mutation signatures clean, are reusable, and evolve more gracefully than many positional args.
4. Default Values
Arguments can declare defaults in the schema or in variable declarations, so callers may omit them:
type Query {
posts(first: Int = 10, order: SortOrder = DESC): [Post!]!
}
5. Arguments on Nested Fields
Arguments aren't limited to the top level - any field can take them:
query {
user(id: "42") {
posts(first: 3, status: PUBLISHED) { # nested-field arguments
comments(last: 2) { text } # deeper still
}
}
}
Why Variables Beat Inline Literals
- Reusability: one query document, many inputs.
- Safety: user input goes in the variables JSON, not concatenated into the query string (avoids injection-style mistakes and quoting bugs).
- Caching/tooling: stable query strings are easier to cache, persist, and analyze.
- Typing: the server validates variable types before executing.
Why This Matters in Interviews
GraphQL interviews use this to test schema and query fluency. Cover all the mechanisms - inline literals, variables ($var, with ! for required and = default), input types for bundling mutation arguments, default values, and nested-field arguments. The maturity signal is recommending variables/input types over inline literals and explaining why (reuse, safety, typing). Knowing input types are the idiomatic way to pass mutation payloads is commonly expected.
Common Pitfalls
- Concatenating user input into inline query strings instead of using variables.
- Forgetting
!for required arguments (or adding it where optional is intended). - Passing many loose arguments to a mutation instead of a single
inputtype. - Mismatching the variable's declared type with the schema's expected type.
- Assuming arguments only work at the top level (nested fields take them too).
References
- GraphQL arguments: https://graphql.org/learn/queries/#arguments
- GraphQL variables & input types: https://graphql.org/learn/queries/#variables