Top 60 GraphQL Interview Questions (2026)

The 60 GraphQL questions interviewers actually ask, with direct answers, runnable queries and schemas, and what the interviewer is listening for. Grouped for freshers, intermediate, and experienced rounds.

60 questions with answers

What Is GraphQL?

Key Takeaways

  • GraphQL is a query language for APIs and a runtime for answering those queries against a typed schema you define.
  • Clients ask for exactly the fields they need in one request, which cuts over-fetching and under-fetching that plague fixed REST endpoints.
  • Interviews test the schema (types, queries, mutations, subscriptions), resolvers and the N+1 problem, and how GraphQL compares to REST, not just query syntax.
  • This page is a question bank: work your tier first, read one tier up, and say answers out loud because delivery is evaluated too.

GraphQL is a query language for APIs and a server-side runtime that resolves those queries against a strongly typed schema. Facebook built it internally in 2012, open-sourced it in 2015, and it now sits under the GraphQL Foundation. Instead of many fixed endpoints, a GraphQL API exposes a single endpoint whose schema describes every type and field a client can ask for. The client sends a query naming exactly the fields it wants, and the server returns a JSON shape that matches. That single idea removes over-fetching (getting fields you don't need) and under-fetching (needing several round trips), which is the problem REST hits as UIs grow. In interviews, GraphQL questions probe the schema and type system, how resolvers turn a query into data, the N+1 query trap and how DataLoader fixes it, and the honest trade-offs against REST. The official introduction from the GraphQL Foundation at graphql.org/learn is the canonical starting point, and this page collects the 60 questions that come up most, each with a direct answer and runnable query or schema. Increasingly the first round is a live AI coding interview, so pair this bank with our AI interview preparation guides for the format side.

60Questions with answers on this page
3Difficulty tiers: freshers, intermediate, experienced
20+Runnable GraphQL snippets you can practice from
2015Year GraphQL was open-sourced by Facebook

Watch: Learn GraphQL In 40 Minutes

Video: Learn GraphQL In 40 Minutes (Web Dev Simplified, YouTube)

Test yourself and earn a certificate

10 quick questions. Score 70%+ to download your GraphQL certificate.

Jump to quiz

All Questions on This Page

60 questions
GraphQL Interview Questions for Freshers
  1. 1. What is GraphQL and why was it created?
  2. 2. How is GraphQL different from REST?
  3. 3. What is a GraphQL schema?
  4. 4. What are queries, mutations, and subscriptions?
  5. 5. What is a resolver?
  6. 6. Why does GraphQL use a single endpoint?
  7. 7. What are over-fetching and under-fetching?
  8. 8. How do you pass arguments to a field?
  9. 9. What are variables in a GraphQL query?
  10. 10. What is a fragment and why use one?
  11. 11. What are the built-in scalar types in GraphQL?
  12. 12. What do ! and [] mean in the schema?
  13. 13. What is introspection?
  14. 14. What are aliases and when do you need them?
  15. 15. Is GraphQL a database or tied to one?
  16. 16. What is the difference between object types and scalar types?
  17. 17. What does a GraphQL response look like?
  18. 18. What are input types?
  19. 19. What is an enum type in GraphQL?
  20. 20. What is GraphiQL?
  21. 21. How do you document a schema?
  22. 22. Can arguments have default values?
  23. 23. What is the __typename meta-field?
  24. 24. Why do most GraphQL requests use POST?
GraphQL Intermediate Interview Questions
  1. 25. What are the four arguments every resolver receives?
  2. 26. What is the N+1 problem in GraphQL?
  3. 27. How does DataLoader fix the N+1 problem?
  4. 28. How does caching work with GraphQL?
  5. 29. What are interfaces in GraphQL?
  6. 30. What is a union type and how does it differ from an interface?
  7. 31. What are directives, and which ones are built in?
  8. 32. How does error handling work in GraphQL?
  9. 33. How should you design a mutation and its response?
  10. 34. How do you paginate in GraphQL?
  11. 35. What is the Relay Connections specification?
  12. 36. How do you handle authentication and authorization?
  13. 37. How do subscriptions work and what transport do they use?
  14. 38. What is the difference between schema-first and code-first?
  15. 39. How do you stop a client from sending an expensive query?
  16. 40. How do you decide which fields should be non-null?
  17. 41. How do fragments help with client caching?
  18. 42. In what order do resolvers run for a nested query?
  19. 43. Why should the context (and DataLoaders) be created per request?
  20. 44. How do you version a GraphQL API?
GraphQL Interview Questions for Experienced Developers
  1. 45. What actually happens when a GraphQL query reaches the server?
  2. 46. What is GraphQL federation and what problem does it solve?
  3. 47. How does schema stitching differ from federation?
  4. 48. What are persisted queries and why use them?
  5. 49. What are the main security concerns specific to GraphQL?
  6. 50. How do you monitor a GraphQL API in production?
  7. 51. How do you test a GraphQL API?
  8. 52. Beyond DataLoader, how else do you attack the N+1 problem?
  9. 53. How do you implement a custom scalar, and what are the risks?
  10. 54. Why did Facebook build GraphQL, and what did it replace?
  11. 55. What principles guide good GraphQL schema design?
  12. 56. How do you roll out a breaking schema change safely?
  13. 57. What are the trade-offs of a normalized client cache?
  14. 58. Why should query resolvers be free of side effects?
  15. 59. In a real project, how do you decide between GraphQL and REST?
  16. 60. Design question: how would you put a GraphQL layer in front of several existing REST and database services?

GraphQL Interview Questions for Freshers

Freshers24 questions

The fundamentals every entry-level round checks. If any answer here surprises you, that's your study list.

Q1. What is GraphQL and why was it created?

GraphQL is a query language for APIs and a runtime that resolves those queries against a typed schema. Facebook built it in 2012 and open-sourced it in 2015. Instead of many fixed endpoints, one endpoint serves a schema, and the client asks for exactly the fields it needs.

It was created to solve over-fetching and under-fetching in mobile apps: fixed REST endpoints either returned too much data or forced several round trips. Letting the client shape the response fixed both.

Key point: Lead with 'query language plus runtime,' then the problem it solves. Interviewers open with this to hear how you frame an answer.

Watch a deeper explanation

Video: GraphQL Explained in 100 Seconds (Fireship, YouTube)

Q2. How is GraphQL different from REST?

REST exposes many endpoints, each with a server-decided response shape. GraphQL exposes one endpoint and a query language, so the client decides which fields come back. That removes over-fetching and the extra round trips REST needs as a UI grows.

The cost is that GraphQL loses easy per-URL HTTP caching and pushes more logic to the server. Neither is strictly better; they trade client flexibility against server and caching simplicity.

AspectGraphQLREST
EndpointsOneMany
Response shapeClient-chosen fieldsFixed by server
Round tripsOften oneOften several
CachingClient or normalized storeHTTP and CDN, per URL

Key point: End with 'when would you still use REST?'. Naming a case (small stable API, file downloads) indicates judgment, not GraphQL fandom.

Watch a deeper explanation

Video: GraphQL Crash Course #1 - What is GraphQL? (Net Ninja, YouTube)

Q3. What is a GraphQL schema?

The schema is the contract of a GraphQL API. It defines every type, every field, and the entry-point operations (Query, Mutation, Subscription). Written in the Schema Definition Language, it tells clients exactly what they can ask for and what shape comes back.

Because the schema is strongly typed, tools can validate queries before running them and generate documentation and client code automatically.

graphql
type User {
  id: ID!
  name: String!
  email: String
}

type Query {
  user(id: ID!): User
  users: [User!]!
}

Q4. What are queries, mutations, and subscriptions?

They're the three root operation types a schema can expose. Queries read data, mutations change it, and subscriptions stream real-time updates over a persistent connection. Every request you send is one of these three, and each maps to a root type in the schema (Query, Mutation, Subscription) that holds its entry-point fields.

By convention queries have no side effects, mutations do, and subscriptions push new data to the client when a server-side event fires, usually over WebSockets.

graphql
query { user(id: 1) { name } }

mutation { addUser(name: "Asha") { id } }

subscription { userAdded { id name } }

Key point: The follow-up is 'what transport does a subscription use?'. WebSockets is the common answer; server-sent events also work.

Q5. What is a resolver?

A resolver is a function that returns the value for one field. When a query arrives, the server calls a resolver for each requested field, and the results assemble into the response.

A resolver receives four arguments: the parent value, the field's arguments, a shared context object (auth, loaders), and info about the query. Fields without an explicit resolver fall back to reading the property of the same name off the parent.

javascript
const resolvers = {
  Query: {
    user: (parent, args, context) => db.findUser(args.id),
  },
  User: {
    fullName: (user) => `${user.first} ${user.last}`,
  },
};

Q6. Why does GraphQL use a single endpoint?

One endpoint means the schema, not the URL, describes what's available. Clients send every query and mutation to the same URL (commonly /graphql) and select fields inside the request body instead of choosing among many routes.

This is what makes client-driven field selection possible: there's no fixed resource URL that pins the response shape.

Q7. What are over-fetching and under-fetching?

Over-fetching is getting back more data than the screen needs, wasting bandwidth on fields you'll never render. Under-fetching is the opposite: a single request doesn't return enough, so the client makes extra round trips to other endpoints to fill in the gaps. REST tends to cause both because each endpoint has one fixed response shape.

REST hits both because each endpoint has a fixed shape. GraphQL avoids both because the client lists the exact fields it wants in one request.

Key point: Give a concrete example: a profile card that needs a name and avatar but the REST /user endpoint returns thirty fields. Concreteness lands better than the definition alone.

Q8. How do you pass arguments to a field?

Fields can take arguments in parentheses, like user(id: 1) or posts(first: 10). Arguments filter, paginate, or shape what a field returns, and the schema declares each argument's name and type so the server can validate them. If a required argument is missing or the type is wrong, the query fails validation before any resolver runs.

Any field can have arguments, not just top-level ones, which is how you page a nested list inside a larger query.

graphql
query {
  user(id: 1) {
    name
    posts(first: 3) {
      title
    }
  }
}

Q9. What are variables in a GraphQL query?

Variables let you parameterize a query instead of hardcoding values into the query string. You declare them with a $ name and a type, then pass a separate variables object at request time.

This keeps the query static and reusable, avoids string concatenation, and lets the server parse and cache the query text once.

graphql
query GetUser($id: ID!) {
  user(id: $id) {
    name
  }
}

# variables: { "id": "1" }

Q10. What is a fragment and why use one?

A fragment is a named, reusable set of fields you can spread into multiple queries with the ... syntax. It removes duplication when several queries need the same slice of a type.

Fragments also keep large queries readable and let UI frameworks colocate the data a component needs next to that component.

graphql
fragment UserCard on User {
  id
  name
  avatarUrl
}

query {
  user(id: 1) { ...UserCard }
  users { ...UserCard }
}

Q11. What are the built-in scalar types in GraphQL?

GraphQL ships with five scalars: Int, Float, String, Boolean, and ID. Scalars are the leaf values in a query, so every field path eventually resolves to one of them. You can't return a scalar-less object; a query keeps drilling into object fields until each branch ends at a scalar that holds an actual value.

ID is a String under the hood but signals a unique identifier and is serialized as a string. You can also define custom scalars like Date or Email with your own validation.

ScalarRepresents
Int32-bit signed integer
FloatDouble-precision floating point
StringUTF-8 text
Booleantrue or false
IDUnique identifier, serialized as a string

Q12. What do ! and [] mean in the schema?

A trailing ! marks a field or argument as non-null: the server promises it won't return null there. Square brackets make a list type, so [String] is a list of strings.

The two combine, and position matters. [String!]! is a non-null list of non-null strings: the list itself can't be null, and no element can be null either.

graphql
type Post {
  id: ID!            # never null
  tags: [String!]!   # non-null list of non-null strings
  author: User       # may be null
}

Key point: The gotcha follow-up: if a non-null field resolves to null, the error bubbles up to the nearest nullable parent. Knowing that shows you've read the spec.

Q13. What is introspection?

Introspection lets a client query the schema itself: what types exist, what fields they have, and what arguments each takes. You call it with the special __schema and __type fields.

It powers tooling: GraphiQL autocomplete, client code generation, and API docs all read the schema through introspection. Many teams disable it in production to reduce the API surface exposed to outsiders.

graphql
query {
  __schema {
    types { name }
  }
}

Q14. What are aliases and when do you need them?

An alias renames a field in the response. You need one when a query requests the same field twice with different arguments, because a JSON object can't have two keys with the same name.

Aliases also let a client shape the response keys to match its own model without changing the schema.

graphql
query {
  first: user(id: 1) { name }
  second: user(id: 2) { name }
}

Q15. Is GraphQL a database or tied to one?

No. GraphQL is a layer over your existing data, not a storage engine. Resolvers can pull from a SQL database, a REST API, a cache, a file, or several sources at once inside one query.

This is a common misconception. GraphQL describes what clients can ask for; how each field gets its data is entirely up to your resolvers.

Key point: If you can name three different backing sources a single query might touch, you've shown you understand the resolver model.

Q16. What is the difference between object types and scalar types?

Object types have fields and describe the shape of an entity, like User or Post. Scalar types are the concrete leaf values, like String or Int, that those fields eventually resolve to.

Every query is a tree that starts at an object type and drills down until every branch ends in a scalar. You can't return an object type without selecting fields on it.

Q17. What does a GraphQL response look like?

The response is JSON with a top-level data key whose shape mirrors the query, plus an optional errors array. Ask for name and email and you get back exactly a name and email under data.

Because the response shape follows the query, clients know the structure in advance and don't parse unpredictable payloads.

json
{
  "data": {
    "user": { "name": "Asha", "email": "asha@example.com" }
  }
}

Q18. What are input types?

Input types are object-like types used only for arguments, especially in mutations. You can't pass a regular object type as an argument; you define an input type with the input keyword instead.

Grouping many arguments into one input object keeps mutation signatures clean and makes them easier to evolve.

graphql
input CreateUserInput {
  name: String!
  email: String!
}

type Mutation {
  createUser(input: CreateUserInput!): User
}

Q19. What is an enum type in GraphQL?

An enum restricts a field to a fixed set of named values, like a Role of ADMIN, EDITOR, or VIEWER. The server validates that only those values are used, in queries and in responses.

Enums document intent and prevent typos: an invalid value fails validation before any resolver runs.

graphql
enum Role {
  ADMIN
  EDITOR
  VIEWER
}

type User {
  role: Role!
}

Q20. What is GraphiQL?

GraphiQL is an in-browser IDE for exploring a GraphQL API. It gives you autocomplete, inline documentation, and a query editor with live results, all built on introspection of the schema. You type a query on one side, run it, and see the JSON response on the other, which makes it the fastest way to learn an unfamiliar API.

It's the tool most people first meet GraphQL through. In an interview, it matters.

Q21. How do you document a schema?

Use description strings: text in double quotes placed right above a type, field, or argument in the SDL. These descriptions show up in GraphiQL and generated docs, so the schema documents itself.

This is different from a # comment, which is ignored and never surfaced. Descriptions travel with the schema through introspection.

graphql
"""A person who can sign in."""
type User {
  """Primary email, used for login."""
  email: String!
}

Q22. Can arguments have default values?

Yes. An argument can declare a default with = in the schema, so clients that omit it get the default. This is common for pagination arguments like first: Int = 10.

Defaults keep queries short and give the server a sane fallback without forcing every caller to specify every argument.

graphql
type Query {
  posts(first: Int = 10): [Post!]!
}

Q23. What is the __typename meta-field?

__typename is a built-in field available on every object type that returns the name of that type as a string. You can add it to any selection, and it comes back without being defined in the schema.

It's most useful with interfaces and unions, where the client needs to know which concrete type a result is. Normalized caches also read it, combined with the id, to key each object.

graphql
query {
  search(q: "graphql") {
    __typename
    ... on Book { title }
    ... on Author { name }
  }
}

Q24. Why do most GraphQL requests use POST?

Queries can be long and are sent in the request body, which fits POST. GET works for simple queries by putting the query in the URL, but bodies avoid URL length limits and are the common default.

The side effect is that per-URL HTTP caching doesn't apply, since every request hits the same endpoint with a body. That's why GraphQL caching usually lives in the client instead.

Key point: Connecting POST to the caching trade-off, rather than stopping at 'it uses POST,' is what separates a fresher who memorized from one who understood.

Back to question list

GraphQL Intermediate Interview Questions

Intermediate20 questions

For candidates with working experience: resolver mechanics, the N+1 problem, caching, and the questions that separate users from understanders.

Q25. What are the four arguments every resolver receives?

A resolver gets parent (the value from the resolver one level up), args (the field's arguments), context (a per-request object holding auth, loaders, and shared services), and info (details about the query, like the field name and path).

The context is the one to know well: it's how you pass the authenticated user and DataLoaders into every resolver without global state.

javascript
const resolvers = {
  Query: {
    me: (parent, args, context, info) => context.currentUser,
  },
};

Key point: If asked 'where does the logged-in user come from?', the technical answer is context, populated once per request before resolvers run.

Q26. What is the N+1 problem in GraphQL?

When a query returns a list and each item resolves a related field, a naive server makes one query for the list and then one more per item: N+1 database calls. Fetch 100 posts and their authors and you've fired 101 queries.

It happens because resolvers run per field per item, with no built-in batching. It's the single most common GraphQL performance bug.

javascript
// N+1: this author resolver runs once per post
Post: {
  author: (post) => db.getUser(post.authorId),
}
// 1 query for posts + N queries for authors

Key point: This is the setup for the DataLoader question. Interviewers almost always chain them, so have the fix ready.

Watch a deeper explanation

Video: GraphQL Course for Beginners (freeCodeCamp.org, YouTube)

Q27. How does DataLoader fix the N+1 problem?

DataLoader batches and caches. Instead of loading each item immediately, resolvers call loader.load(id), and DataLoader collects all the ids requested in one tick, then hands them to a single batch function that fetches them in one query. It also caches by key within the request, so repeated ids don't refetch.

So N+1 collapses to two calls: one for the list, one batched call for all related items.

javascript
const userLoader = new DataLoader(async (ids) => {
  const users = await db.getUsersByIds(ids);   // one query
  return ids.map((id) => users.find((u) => u.id === id));
});

// resolver
author: (post) => userLoader.load(post.authorId),

How DataLoader batches a request

1Resolvers call load(id)
each author field asks for its id, no fetch yet
2DataLoader collects ids
all ids requested in the same tick are queued
3Batch function runs once
one query fetches every queued id together
4Results map back
each load() promise resolves with its item, cached by key

Create a fresh DataLoader per request so its cache never leaks data between users.

Q28. How does caching work with GraphQL?

Per-URL HTTP caching mostly doesn't apply, because queries POST to one endpoint. Caching moves to three other places: client-side normalized caches (Apollo Client, Relay) that store objects by id, server-side response or resolver caching, and persisted queries that let a GET-cacheable hash stand in for a full query.

The key idea for interviews: GraphQL trades REST's simple HTTP caching for a normalized client cache keyed by object identity.

LayerExampleWhat it caches
Client normalizedApollo Client, RelayObjects by type and id
Server responseResponse or resolver cacheWhole or partial results
Persisted queriesHashed query + GETEnables CDN and HTTP caching

Q29. What are interfaces in GraphQL?

An interface is an abstract type listing fields that several object types must implement. A SearchResult query might return anything implementing a Node interface with an id field, and each concrete type adds its own fields.

Clients query shared interface fields directly and use inline fragments (... on Book) to pull type-specific fields. Your schema must provide a way to resolve which concrete type each value is.

graphql
interface Node {
  id: ID!
}

type Book implements Node {
  id: ID!
  title: String!
}

type Author implements Node {
  id: ID!
  name: String!
}

Q30. What is a union type and how does it differ from an interface?

A union says a field can return one of several object types that share no required fields, like SearchResult = Book | Author. Unlike an interface, a union declares no common fields, so clients must use inline fragments for every branch.

Rule of thumb: use an interface when the types share fields you'll query in common, and a union when they don't.

graphql
union SearchResult = Book | Author

query {
  search(q: "graphql") {
    ... on Book { title }
    ... on Author { name }
  }
}

Key point: The distinction the question needs: interface = shared fields, union = no shared fields. Say that first, then show the inline-fragment syntax.

Q31. What are directives, and which ones are built in?

A directive is an annotation, marked with @, that changes execution or schema behavior. The two built-in query directives are @include(if:) and @skip(if:), which conditionally add or drop a field based on a variable. @deprecated marks a schema field as deprecated with a reason.

You can also define custom directives for cross-cutting concerns like authorization or formatting, applied in the schema or the query.

graphql
query GetUser($withEmail: Boolean!) {
  user(id: 1) {
    name
    email @include(if: $withEmail)
  }
}

Q32. How does error handling work in GraphQL?

A GraphQL response can carry both data and an errors array, and partial success is normal: if one field fails, its resolver's error lands in errors while other fields still return under data. Most servers respond with HTTP 200 even when errors are present.

Because HTTP status codes don't map cleanly to field errors, teams add structured error codes inside errors[].extensions so clients can branch on a stable code rather than parse messages.

json
{
  "data": { "user": null },
  "errors": [
    { "message": "Not found", "extensions": { "code": "NOT_FOUND" } }
  ]
}

Q33. How should you design a mutation and its response?

Take a single input type argument, and return a payload type rather than a bare entity. The payload includes the affected object plus room for a status or errors field, so one mutation can report both success data and validation problems.

Returning the mutated object lets the client update its cache from the response without a second query, which is why normalized clients rely on it.

graphql
type Mutation {
  createUser(input: CreateUserInput!): CreateUserPayload!
}

type CreateUserPayload {
  user: User
  userErrors: [UserError!]!
}

Q35. What is the Relay Connections specification?

It's a convention for cursor-based pagination. A connection wraps results in edges, each with a node and a cursor, plus a pageInfo object holding hasNextPage and endCursor. It standardizes how lists paginate so tooling can rely on the shape.

You don't have to use Relay the client to adopt the pattern; many schemas follow the connection shape regardless of which client consumes them.

graphql
type PostConnection {
  edges: [PostEdge!]!
  pageInfo: PageInfo!
}
type PostEdge {
  node: Post!
  cursor: String!
}
type PageInfo {
  hasNextPage: Boolean!
  endCursor: String
}

Q36. How do you handle authentication and authorization?

Authentication happens before GraphQL: verify the token (JWT, session cookie) in HTTP middleware and put the resulting user on the context. GraphQL itself has no login step; it reads context.currentUser.

Authorization then lives in resolvers or a directive: check the current user's permissions per field or per object before returning data. Field-level checks matter because one query can reach many types at once.

javascript
adminPanel: (parent, args, context) => {
  if (context.user?.role !== "ADMIN") {
    throw new GraphQLError("Forbidden", { extensions: { code: "FORBIDDEN" } });
  }
  return getPanel();
},

Key point: The point interviewers probe: put auth in context, enforce per field. A single query can touch many types, so one gate at the endpoint isn't enough.

Q37. How do subscriptions work and what transport do they use?

A subscription opens a long-lived connection, and the server pushes a new payload whenever a matching event fires: a new message, a price change. The client subscribes once and receives a stream, unlike a query that returns once.

The common transport is WebSockets, usually via the graphql-ws protocol; server-sent events are an alternative for one-way streams. Under the hood you publish events to a pub/sub system that the subscription resolver listens to.

graphql
type Subscription {
  messageAdded(channelId: ID!): Message!
}

Q38. What is the difference between schema-first and code-first?

Schema-first: you write the SDL by hand as the source of truth, then implement resolvers to match. Code-first: you define types in your programming language (with a library like Nexus or Pothos or type-graphql) and the SDL is generated from that code.

Schema-first reads clearly and keeps the contract front and center; code-first keeps types and resolvers together and gives you the type safety of your language. Teams pick based on which drift they'd rather avoid.

ApproachSource of truthTrade-off
Schema-firstHand-written SDLClear contract, resolvers can drift from it
Code-firstProgram codeType-safe, SDL is generated not authored

Q39. How do you stop a client from sending an expensive query?

GraphQL lets clients build deeply nested queries, which can be abused. Defenses stack: cap query depth, assign each field a cost and reject queries over a complexity budget, set a timeout, and paginate all lists so nothing returns unbounded.

For public APIs, persisted queries go further by only allowing a pre-approved allowlist of queries, so arbitrary expensive shapes never reach the server.

  • Depth limiting: reject queries nested past N levels.
  • Cost analysis: sum per-field weights, reject over a budget.
  • Timeouts and pagination: bound execution time and list sizes.
  • Persisted query allowlists: only run known-safe queries.

Q40. How do you decide which fields should be non-null?

Mark a field non-null only when you can truly guarantee it. A non-null field that resolves to null triggers an error that bubbles up to the nearest nullable parent, which can wipe out a whole branch of an otherwise good response.

The safe default for fields that depend on external data (a joined record, a remote call) is nullable, so a single missing value degrades gracefully instead of erroring the parent object.

Key point: Saying 'I default to nullable and earn non-null' signals you've been burned by a non-null field nulling out a parent in production.

Q41. How do fragments help with client caching?

A normalized client caches objects by type and id. Fragments that always include the id let the client match a returned object to its cache entry and update every query that referenced that object, no refetch needed.

So fragments aren't only about reuse in query text; they help the cache stay consistent because the same fields (including id) come back the same way everywhere.

Q42. In what order do resolvers run for a nested query?

Top-down and depth-first, following the query tree. A field's resolver runs, its return value becomes the parent for its child resolvers, and so on down the selection. Sibling fields at the same level can resolve in parallel since they don't depend on each other.

This ordering is why the parent argument matters: a child resolver reads from whatever its parent resolver returned.

Q43. Why should the context (and DataLoaders) be created per request?

Context carries request-specific state: the authenticated user and per-request caches. If you share one DataLoader across requests, its cache would serve user A's data to user B, which is a data leak, and stale entries would never clear.

A fresh context and fresh loaders per request scope the cache to that request, so batching helps within a request and nothing bleeds across users.

Q44. How do you version a GraphQL API?

GraphQL avoids URL versions like /v2. Instead you evolve the schema in place: add new fields and types freely (they're backward-compatible), and retire old ones with @deprecated plus a reason so clients migrate before you remove them.

Because clients request only the fields they use, adding fields never breaks existing queries. Removing or changing a field is the breaking act, and deprecation is how you stage it.

graphql
type User {
  fullName: String!
  name: String! @deprecated(reason: "Use fullName")
}
Back to question list

GraphQL Interview Questions for Experienced Developers

Experienced16 questions

advanced rounds probe execution internals, federation, design judgment, and production scars. Expect every answer here to draw a follow-up.

Q45. What actually happens when a GraphQL query reaches the server?

Three phases. Parse turns the query string into an abstract syntax tree. Validate checks that AST against the schema: do the fields exist, do the types line up, are required arguments present. Execute walks the tree, calling resolvers field by field and assembling the result, then serializes it to JSON.

Senior-level extras: validation is where malformed or invalid queries fail fast before any resolver runs, and execution is where batching (DataLoader) and cost limits hook in.

The query execution pipeline

1Parse
query text becomes an abstract syntax tree
2Validate
check fields, types, and arguments against the schema
3Execute
run resolvers over the tree, top-down
4Serialize
assemble the data and errors into JSON

Invalid queries die in validation, before any resolver or database call runs.

Q46. What is GraphQL federation and what problem does it solve?

Federation composes one supergraph from many independently owned subgraph services. Each team owns a slice of the schema, and a gateway plans and stitches queries across subgraphs, so a client still sees a single unified graph.

It solves the monolith problem: without federation, one giant schema and resolver layer becomes a shared bottleneck. Federation lets teams ship their part of the graph on their own cadence while types can reference each other across service boundaries.

Key point: The follow-up is 'how does a type get extended across services?'. Mention entity keys and the @key directive, which is how one subgraph resolves fields the owning subgraph defined.

Q47. How does schema stitching differ from federation?

Both combine multiple schemas into one. Schema stitching does it at the gateway by merging schemas and writing delegation logic centrally, so the gateway holds the knowledge of how services connect. Federation inverts that: each subgraph declares its own relationships with directives, and the gateway composes them, so ownership stays with the teams.

Federation is the more maintainable pattern for many teams because coordination lives in the subgraphs, not in one central stitching layer that every change has to touch.

AspectSchema stitchingFederation
Where relationships liveCentral gatewayEach subgraph declares its own
Team ownershipGateway team coordinatesSubgraph teams stay independent
Cross-service typesManual delegationEntity keys and directives

Q48. What are persisted queries and why use them?

A persisted query registers a query text on the server ahead of time and gives it a hash. Clients then send the hash (and variables) instead of the full query string. Automatic persisted queries do this on the fly: send the hash, and only send the full text if the server hasn't seen it yet.

The wins: smaller requests over the wire, a GET-cacheable request that CDNs can cache, and a security allowlist, because the server can refuse any query hash it didn't register. That turns off arbitrary expensive queries on public APIs.

Q49. What are the main security concerns specific to GraphQL?

The big ones: malicious deep or wide queries that exhaust resources, introspection exposing your full schema to attackers, batching and aliasing used to amplify a single request into thousands of operations, and field-level authorization gaps where one query reaches data a user shouldn't see.

Defenses: depth and cost limits, disable introspection in production or gate it, rate-limit and cap batch/alias counts, and enforce authorization per field or per object rather than only at the endpoint.

  • Query cost and depth limits against resource exhaustion.
  • Introspection disabled or gated in production.
  • Alias and batch caps against amplification attacks.
  • Per-field authorization, not just endpoint-level auth.

Q50. How do you monitor a GraphQL API in production?

Per-endpoint metrics don't help when everything hits /graphql, so you instrument at the field and operation level: track latency and error rate per resolver, per operation name, and per client. Tracing (Apollo tracing, OpenTelemetry spans per resolver) shows which field in a query is slow.

Operation names and persisted queries make this practical: you can attribute load to specific queries and specific teams, then find the N+1 or the slow downstream call by resolver, not by URL.

Q51. How do you test a GraphQL API?

Layer it. Unit-test resolvers as plain functions with a mocked context. Integration-test by executing real queries against the schema (in-process, no HTTP) and asserting on data and errors. End-to-end test the deployed endpoint for auth and transport. Add schema checks in CI to catch breaking changes before they ship.

The schema-diff check is the one people forget: comparing the proposed schema against the current one flags removed or changed fields that would break live clients.

javascript
const res = await server.executeOperation({
  query: "query { user(id: 1) { name } }",
});
expect(res.body.singleResult.errors).toBeUndefined();
expect(res.body.singleResult.data.user.name).toBe("Asha");

Q52. Beyond DataLoader, how else do you attack the N+1 problem?

DataLoader batches at the resolver layer, but other tactics help. Look-ahead resolution reads the query info to see which nested fields are requested and issues a single joined query up front. A projection or a query builder can turn a known selection set into one SQL statement. And for read-heavy graphs, a well-placed cache on hot entities cuts repeated loads.

The senior instinct is to fetch by the shape of the whole query, not field by field, when the data source supports it.

Q53. How do you implement a custom scalar, and what are the risks?

A custom scalar (DateTime, Email, JSON) needs three functions: serialize (internal value to the client), parseValue (variable input to internal), and parseLiteral (inline literal to internal). You define validation in those functions so bad values fail at the boundary.

The risk to name is JSON as a scalar: it escapes the type system entirely, so the schema stops describing that data and clients lose validation and tooling. Use typed structures instead of a JSON blob unless the data is genuinely unstructured.

javascript
const DateTime = new GraphQLScalarType({
  name: "DateTime",
  serialize: (v) => v.toISOString(),
  parseValue: (v) => new Date(v),
  parseLiteral: (ast) => new Date(ast.value),
});

Q54. Why did Facebook build GraphQL, and what did it replace?

Facebook's mobile apps were straining against REST: fetching a news feed meant many round trips and either too much or too little data on slow networks. They needed the client to describe its data needs in one request that mapped to a rich, connected object graph.

GraphQL replaced that fan-out of REST calls with a single declarative query. Knowing the origin story matters because it explains every design choice: one endpoint, client-chosen fields, a strong type system, all aimed at data fetching for product UIs.

Watch a deeper explanation

Video: React.js Conf 2015 - Data fetching for React applications at Facebook (Meta Developers, YouTube)

Q55. What principles guide good GraphQL schema design?

Design the schema around the client's view of the domain, not your database tables. Prefer clear entity types with real relationships over flat CRUD. Make mutations specific and intent-revealing (publishPost, not a generic update). Default fields to nullable unless you can guarantee them, and use input and payload types so mutations can evolve.

The recurring senior theme: the schema is a long-lived public contract, so optimize it for the consumers and for change, not for whatever's convenient on the server today.

Q56. How do you roll out a breaking schema change safely?

You avoid breaking changes when you can and stage them when you can't. Add the new field alongside the old, deprecate the old with a reason, and use analytics on field usage (many servers track which fields each client queries) to confirm no one still calls the old one before you remove it.

Schema registries and CI schema checks gate merges that would break known operations. The whole point is that removal is a controlled event driven by real usage data, not a guess.

Key point: field-usage analytics as the trigger for safe removal is the answer that matters.

Q57. What are the trade-offs of a normalized client cache?

A normalized cache (Apollo, Relay) stores each object once by type and id, so updating one object updates every query showing it, and refetches shrink. The cost is real complexity: the cache needs stable ids everywhere, list updates after a mutation need explicit cache logic, and pagination merging is fiddly.

The judgment call is when it earns that complexity. For a data-heavy app with lots of shared entities across screens, it pays off; for a simple app, a plain fetch cache may be enough.

Q58. Why should query resolvers be free of side effects?

The execution engine can run sibling resolvers in parallel, reorder within the tree's constraints, and (with tools) batch or cache field results. If a query resolver writes data or depends on execution order, those optimizations become bugs, and the same query returns different results run to run.

Side effects belong in mutations, which the spec runs serially precisely because order matters for writes. Keeping queries pure is what makes the engine's freedom safe.

Q59. In a real project, how do you decide between GraphQL and REST?

Reach for GraphQL when many clients need different slices of a rich, connected graph, when mobile and web share a backend and want to minimize round trips, or when frontend teams need to iterate on data needs without waiting on new endpoints. Stay with REST for small stable APIs, heavy file transfer, when strong HTTP and CDN caching is a hard requirement, or when the team has no appetite for the server-side machinery GraphQL asks for.

The honest coverage names the cost: GraphQL moves complexity to the server (resolvers, N+1 guards, cost limits, caching you build yourself). It's a real trade, not a free upgrade.

Key point: The technical decision depends on whether you pick on the requirements in front of you, not on hype.

Q60. Design question: how would you put a GraphQL layer in front of several existing REST and database services?

Clarify first: which services, read-heavy or write-heavy, one team or many. Then design the schema around the client's domain, not the underlying services, and write resolvers that call each REST API or database, wrapping every downstream call in a DataLoader to batch and prevent N+1. Put auth on the context, add depth and cost limits, and cache hot reads at the resolver layer.

If many teams own different services, propose federation so each owns its subgraph and a gateway composes the supergraph. Close on the operational edges: per-resolver tracing to find slow downstreams, timeouts on every external call, and a schema registry with CI checks so the contract evolves safely.

javascript
const resolvers = {
  Query: {
    order: (_, { id }, ctx) => ctx.loaders.order.load(id),
  },
  Order: {
    // batched, so N orders don't fire N calls
    customer: (order, _, ctx) => ctx.loaders.customer.load(order.customerId),
  },
};

Key point: Structuring the answer clarify, schema, resolvers with DataLoader, auth and limits, then operations is what the question is really scoring, more than any single tool.

Watch a deeper explanation

Video: #1 What is GraphQL? | Build a Complete App with GraphQL, Node.js, MongoDB and React.js (Academind, YouTube)

Back to question list

GraphQL vs REST: The Trade-Off It Embodies

GraphQL and REST solve the same job, fetching data over HTTP, with opposite defaults. REST gives you many endpoints with fixed response shapes, so the server decides what you get. GraphQL gives you one endpoint and a query language, so the client decides what it gets. That flexibility removes over-fetching and extra round trips, but it moves complexity to the server: you write resolvers, guard against expensive nested queries, and lose easy HTTP caching. Neither wins outright. GraphQL shines when many clients need different slices of a rich, connected data graph. REST stays simpler for small, stable APIs and file-style resources. Saying that trade-off out loud is itself an interview signal.

ConcernGraphQLREST
EndpointsOne endpoint, typed schemaMany endpoints, one per resource
Data shapeClient picks exact fieldsServer fixes the response shape
Over/under-fetchingAvoided by designCommon as UIs grow
HTTP cachingHard (usually POST, one URL)Easy (GET, per-URL, CDN-friendly)
Error signaling200 with an errors arrayHTTP status codes (404, 500)

How to Prepare for a GraphQL Interview

Prepare in layers, and practice out loud. Most GraphQL rounds move from schema and query concepts to writing resolvers to a design or debugging discussion, so rehearse each stage rather than only reading answers.

  • Master your tier's concepts until you can explain them without notes, then read one tier up for the stretch questions.
  • Type and run every query and resolver; wiring a tiny schema locally cements it far faster than reading.
  • Be ready to draw the request path: query to parse and validate to resolvers to response, because interviewers ask you to trace it.
  • Take the quiz on this page to find weak spots, then revisit those questions before the real round.

The typical GraphQL interview flow

1Recruiter or phone screen
background, why GraphQL, a few concept checks
2Schema and query concepts
types, queries vs mutations, fragments, variables
3Resolvers and live coding
write a resolver, handle the N+1 problem
4Design or debugging
trade-offs vs REST, caching, error handling, follow-ups

Earlier rounds increasingly run as AI coding interviews. The concepts on this page are what gets probed at every stage.

Test Yourself: GraphQL Quiz

Ready to test your GraphQL knowledge?

10 questions, about 6 minutes. Score 70% or higher to earn a shareable certificate.

10 questions Instant feedback Free certificate on 70%+

Frequently  Asked  Questions

Which GraphQL topics should I prioritize before a technical round?

Prioritize the areas that change real decisions: fundamentals, practical tasks, debugging, trade-offs, and evidence. The highest-value questions are tied to a project example, a validation check, or a failure mode.

Do I need to know a specific GraphQL server library?

The concepts transfer across Apollo Server, GraphQL Yoga, graphql-js, Hot Chocolate, and others, so lead with the ideas. If a job posting names a stack, learn its resolver style and its DataLoader equivalent. In the interview, say which library you've used and answer in its terms; interviewers care that you understand the model, not that you memorized one vendor's API.

Are these questions enough to pass a GraphQL interview?

They cover the question-answer portion well, but most GraphQL rounds also include live coding: writing a schema or a resolver while explaining your thinking. wiring a tiny schema and solving small problems out loud with a timer is the practice path. Our AI coding interview prep guide covers that format, including how automated evaluation reads your process.

Should I expect GraphQL vs REST questions?

Almost always. The comparison is the fastest way for an interviewer to check whether you understand why GraphQL exists. Prepare a two-sentence version and a trade-off version: single endpoint and client-chosen fields against harder caching and server-side complexity. Ending with when you'd still pick REST indicates judgment, not GraphQL fandom.

How long does it take to prepare for a GraphQL interview?

If you've shipped GraphQL at work, one to two weeks of an hour a day covers this bank with practice runs. Starting colder, plan three to four weeks, build a small schema with resolvers and a DataLoader, and query it daily; reading answers without running a server is how preparation quietly fails.

Is there a way to test my GraphQL knowledge?

Yes. The quiz on this page scores you as you go and explains every answer, so you find your weak spots fast. Pass the threshold and you can download a shareable certificate with your name and score, free and with no sign-up. It's the quickest way to check yourself before the real round.

From the team that builds coding interviews

Hyring builds the AI Coding Interviewer that runs live technical rounds in 20+ languages for 5,000+ hiring teams. These GraphQL questions and scoring notes reflect what actually gets asked and evaluated inside the interviews we host.

See how the AI Coding Interviewer works

Sources

Adithyan RKWritten by Adithyan RK
Surya N
Fact-checked by Surya N
Published on: 29 May 2026Last updated: 6 Jul 2026
Share: