GraphQL Interview Questions: From Queries to Caching (2026)

Prepare for GraphQL interview questions with 30 answers on schema design, queries, mutations, caching, pagination, errors, security, performance, and frontend tradeoffs.
作者
GreatFrontEnd Team
21 分钟阅读
Jul 9, 2026
GraphQL Interview Questions: From Queries to Caching (2026)

GraphQL interview questions test whether you can turn a typed API contract into a reliable UI. For frontend roles, the interviewer is not only checking syntax. They want to hear how a query maps to a screen, how mutations update visible state, how partial data and errors behave, and how client choices affect backend cost.

The best answers do not say "GraphQL is better than REST." They explain where GraphQL helps, where REST is simpler, and what can go wrong when a flexible query language reaches production.

Use GraphQL Learn, GraphQL over HTTP, GraphQL response format, GraphQL security guidance, GraphQL pagination, GraphQL caching, and Apollo Client cache docs for current terminology.

If REST comparison is your weak spot, pair this with REST API Interview Questions for Frontend Devs and practice explaining the same product screen in both API styles.

What interviewers are testing

AreaWhat to knowHow to answer
SchemaObject types, fields, nullability, enums, interfacesExplain how schema shape becomes frontend data shape
OperationsQueries, mutations, subscriptions, variables, fragmentsShow how operations map to user actions
CachingNormalized cache, IDs, field policies, invalidationExplain what changes after a mutation
ErrorsPartial data, errors, network failuresSeparate GraphQL execution errors from transport errors
Security and costAuth, authorization, depth, persisted documentsSay GraphQL does not remove backend authorization

How frontend GraphQL interviews are different

Backend interviews may spend more time on resolver implementation, schema governance, and database access. Frontend interviews usually probe the client contract:

  • Which fields does this component actually need?
  • What happens while the query loads, fails, or returns partial data?
  • How does the cache change after a mutation?
  • How do pagination, filters, and URL state work together?
  • Which problem belongs to the frontend, the GraphQL layer, or the backing service?

If your answer stays at the definition level, it will sound memorized. Tie every concept to a page, component, request, mutation, or production failure.

30 GraphQL interview questions and answers

1. What problem does GraphQL solve for frontend teams?

GraphQL gives the frontend a typed schema and lets the client select the fields needed for a view. That can reduce overfetching and underfetching, especially when one screen needs data that would otherwise require several REST endpoints.

The tradeoff is that GraphQL shifts work into schema design, resolvers, caching, authorization, and query cost control. A good answer says GraphQL improves the data contract when the graph is designed well, not that it automatically makes every request faster.

Common mistake: Saying "GraphQL prevents overfetching" without mentioning that resolvers can still fetch too much or do expensive backend work.

2. What is the difference between a query, mutation, and subscription?

A query reads data. A mutation represents a write or state-changing operation. A subscription streams updates over a long-lived connection such as WebSocket or server-sent events.

For frontend work, the distinction matters because each operation drives different UI states. A query needs loading, empty, success, partial-error, and retry states. A mutation needs pending, optimistic, success, rollback, validation-error, and duplicate-submit handling. A subscription needs connection, reconnect, stale-event, and auth-expiry behavior.

Interview-ready add-on: A mutation should usually return the changed object or payload the UI needs to update the cache. Returning only success: true often forces a refetch or leaves the client guessing.

3. What is a GraphQL schema?

A schema is the typed contract exposed by a GraphQL server. It defines which operations are available, which object types exist, which fields can be selected, what arguments are accepted, and which values can be null.

For a frontend engineer, the schema is a working client contract. It shapes generated types, component fragments, form input objects, error handling, and the long-term compatibility of old clients.

type Product {
id: ID!
name: String!
price: Money!
imageUrl: String
}
type Query {
product(id: ID!): Product
}

Common mistake: Treating the schema as a JSON response shape. The schema is a contract with validation, nullability, field ownership, and evolution rules.

4. What are scalar, object, enum, and input types?

Scalars are leaf values such as String, Int, Float, Boolean, and ID. Object types contain fields that can be selected. Enums limit a value to a known set of names. Input types describe structured arguments for queries and mutations.

enum SortDirection {
ASC
DESC
}
input ProductFilterInput {
query: String
inStockOnly: Boolean
}

Input types are separate from output object types because output types can contain computed fields, relationships, interfaces, unions, or resolver-only behavior that does not make sense as input.

5. How do non-null fields and null bubbling work?

String! means the field must not be null. [Product!]! means the list itself is not null and none of its items are null. Nullability is a product contract because it decides whether the UI can show partial data or must treat the parent object as unavailable.

If a non-null field resolves to null during execution, GraphQL adds an error and bubbles the null up to the nearest nullable parent. Overusing ! can make a small resolver failure blank out a larger part of the response.

Good answer shape: Explain the UI consequence. A nullable imageUrl lets the product card render a placeholder. A non-null price says the card is not useful without price, so failure should be more visible.

6. Why are variables preferred over string interpolation?

Variables keep the GraphQL document stable while passing dynamic values separately. They are validated by type, easier to reuse, safer than string-building, and friendlier to operation caching or persisted documents.

query ProductDetails($id: ID!) {
product(id: $id) {
id
name
price {
amount
currency
}
}
}

Variables:

{ "id": "product_123" }

Common mistake: Building query strings with template literals and user input. That makes validation, caching, escaping, and operation tracking harder.

7. What are aliases and when would you use them?

Aliases rename response keys. They are useful when querying the same field more than once with different arguments, or when the UI needs two differently named versions of the same schema field.

query CompareProducts {
left: product(id: "product_1") {
id
name
}
right: product(id: "product_2") {
id
name
}
}

Without aliases, both selections would produce the same product key and conflict.

8. How do fragments help?

Fragments define reusable field selections. They are most useful when components own their data needs, because the fragment can live near the component that renders those fields.

fragment ProductCardFields on Product {
id
name
imageUrl
price {
amount
currency
}
}

Fragments improve consistency, but they can also hide overfetching if teams create one large shared fragment for every screen. A useful fragment represents what a component actually renders.

9. What are directives in GraphQL?

Directives annotate parts of a GraphQL document or schema to change behavior. Common built-in directives include @include, @skip, and @deprecated.

query ProductDetails($id: ID!, $showReviews: Boolean!) {
product(id: $id) {
id
name
reviews @include(if: $showReviews) {
rating
body
}
}
}

For frontend interviews, explain directives as part of the data contract. @include can conditionally fetch a field, while @deprecated tells clients a schema field is being phased out.

10. What is a resolver?

A resolver is the server-side function that returns the value for a schema field. It may read from a database, call another API, compute a value, or delegate to another service.

Frontend engineers are not always expected to implement resolvers, but they should understand the cost boundary. One GraphQL request can trigger many resolver calls behind the scenes, so a harmless-looking nested query can be expensive.

const resolvers = {
Query: {
product: (_parent, args, context) => {
return context.productService.findById(args.id);
},
},
};

Good answer shape: Mention the usual resolver inputs: parent value, field arguments, request context, and execution info. Then connect that to auth, batching, and observability.

11. How do GraphQL errors differ from REST errors?

A GraphQL response can contain data and errors together. Request errors, such as syntax, validation, or variable-coercion errors, stop execution and do not include data. Execution errors happen at a response position and may produce partial data; older GraphQL material often calls these field errors.

{
"data": {
"product": {
"id": "product_123",
"name": "Everyday Backpack",
"inventory": null
}
},
"errors": [
{
"message": "Inventory service unavailable",
"path": ["product", "inventory"]
}
]
}

The UI should not automatically turn every GraphQL error into a full-page failure. If the missing field is non-critical, render the safe data and show a local fallback. If the failed field is essential, show a stronger error state.

12. How should auth work in GraphQL?

Authentication identifies the caller. Authorization decides whether that caller can read or mutate a resource or field. Both must be enforced on the server side, usually in resolvers or the service layer behind them.

Do not rely on hiding fields or buttons in the UI. A user can still send a GraphQL operation manually. The frontend can improve UX by hiding unavailable actions, but the server must remain the source of truth.

Good answer shape: Mention authentication headers or cookies, per-resource authorization, consistent error behavior, and audit logging for sensitive mutations.

13. How does GraphQL caching work on the client?

GraphQL does not define client caching by itself. Many clients normalize objects by type name and ID, then store fields separately so different queries can reuse the same entity.

For example, Apollo Client can identify an object using __typename plus id by default. That means a product returned by a list query and a product returned by a detail query can point to the same cache entity.

Cache correctness depends on stable IDs, selected fields, field arguments, pagination merge policy, and mutation responses. If a mutation response omits the changed object's ID, the client may not know which cached entity to update.

14. What should a mutation return?

A mutation should return enough data for the client to update the UI safely. That might be the changed entity, affected list metadata, aggregate counts, or a domain-specific payload with validation errors.

mutation UpdateCartLine($input: UpdateCartLineInput!) {
updateCartLine(input: $input) {
cart {
id
totalItems
subtotal {
amount
currency
}
}
line {
id
quantity
}
userErrors {
field
message
}
}
}

Returning only success: true is weak because the frontend still needs to refetch, guess, or manually patch state without enough information.

15. How would you handle optimistic UI after a mutation?

Optimistic UI updates the interface before the server confirms the mutation. It works well when the operation is likely to succeed and the rollback behavior is clear.

For a cart quantity change, the frontend can show the new quantity immediately, disable repeated clicks while the mutation is pending, and roll back if the server rejects the change because of stock, price, or permission rules.

What to say in interviews: Name the visible states: optimistic value, pending indicator, duplicate-submit protection, rollback, validation error, and final cache consistency.

16. How do you paginate a GraphQL list?

Use cursor-based pagination for feeds and changing lists when possible. The connection pattern returns edges, node, cursor, and pageInfo, which lets the UI request the next page without relying on unstable offsets.

query ProductList($first: Int!, $after: String) {
products(first: $first, after: $after) {
edges {
cursor
node {
id
name
}
}
pageInfo {
hasNextPage
endCursor
}
}
}

The frontend still needs to dedupe by stable ID, preserve scroll position, handle empty states, and avoid appending stale pages after filters change.

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

N+1 happens when resolving a list triggers one extra backend call per item. The frontend sees one GraphQL request, but the server may perform many database or service calls.

Example: a products query returns 40 products, and each product's seller field calls the seller service separately. That becomes one call for the list plus 40 calls for sellers.

Common fixes include batching, request-scoped caching, joining data earlier, or using loader patterns. A frontend engineer should know enough to ask whether expensive fields are batched and whether resolver timing is observable.

18. How do you protect a GraphQL API from expensive operations?

Use layered demand control. For first-party clients, trusted documents can allow only known operations in production. For broader APIs, use pagination, depth limits, breadth or alias limits, batch limits, query complexity analysis, rate limits, timeouts, and monitoring.

Turning off introspection is not enough. It can reduce schema discoverability in non-development environments, but it does not replace authorization, input validation, trusted documents, or operation limits.

Interview-ready answer: "I would control both who can call the API and how expensive each operation can be."

19. What are persisted or trusted documents?

Persisted documents store approved GraphQL operations on the server and let clients send an operation ID, often a hash, instead of the full document. Trusted documents go further by treating those stored operations as an allowlist for first-party production clients.

They can improve security and operations because the server can reject unknown arbitrary documents, track known operation names, and reason about query cost ahead of time.

They do not remove authorization. A known operation can still request data the current user should not see unless the server checks permissions during execution.

20. What is introspection and should it be disabled?

Introspection lets clients query the schema itself. It powers tools, autocomplete, documentation, and code generation.

Disabling introspection can reduce schema discoverability for a private first-party API, but it also removes standard tooling and is not a security boundary. Public GraphQL APIs often leave it enabled. In either case, production security must rely on authorization, trusted documents where appropriate, demand control, and safe error messages.

21. How do file uploads work with GraphQL?

GraphQL can support file uploads through conventions, but uploads often fit better as direct-to-storage or REST-style flows. The frontend concern is not only "can GraphQL upload a file?" It is progress, cancellation, retry, size limits, auth, virus scanning, and what happens if metadata succeeds but upload fails.

A practical answer says: use GraphQL for metadata and signed upload coordination when that keeps the API clean, but do not force large binary transfer through GraphQL just to be consistent.

22. When would you use a custom scalar?

Use a custom scalar when a value needs domain-specific serialization or validation, such as DateTime, URL, EmailAddress, or JSON.

The tradeoff is that clients need to know the runtime format. A schema can say DateTime, but frontend code still needs documentation or generated scalar mappings that explain whether the value is an ISO string, number, or custom object.

23. What is the difference between an interface and a union?

An interface defines shared fields that multiple object types must implement. A union says a field may return one of several object types without requiring shared fields.

Use an interface when the types share a real contract:

interface Node {
id: ID!
}

Use a union for heterogeneous results such as search:

union SearchResult = Product | Article | Brand

In frontend code, both usually require checking __typename before rendering type-specific fields.

24. How do you version a GraphQL API?

Prefer additive schema evolution. Add new fields, deprecate old fields, track operation usage, migrate clients, and remove fields only after the compatibility window.

Avoid changing a field's meaning in place. That is worse than removing it because old clients may keep working syntactically while showing wrong data.

Whole endpoint versioning can exist, but it is usually a last resort for major compatibility breaks. The normal GraphQL path is schema evolution through additive changes and deprecation.

25. How do generated GraphQL types help and where can they hurt?

Generated types catch mismatches between operations and frontend code. They help when a selected field can be null, when a union needs narrowing, or when a mutation input changes.

They can hurt if teams treat generated types as architecture. Codegen cannot fix a vague schema, unstable IDs, unsafe nullability, or a mutation that returns too little data. It is a guardrail, not a replacement for schema ownership.

26. How do subscriptions work and when should you avoid them?

Subscriptions keep a long-lived connection open and push updates when server-side events happen. They are useful for chat, notifications, live dashboards, collaborative editing signals, and other flows where the user benefits from immediate updates.

Avoid subscriptions for data that can be refreshed on navigation, loaded on demand, or polled cheaply. Subscriptions add connection state, auth renewal, reconnect logic, ordering concerns, and server resource cost.

27. How does GraphQL work over HTTP?

GraphQL is not tied to one transport, but HTTP is commonly used for queries and mutations. Many GraphQL APIs send operations to a single endpoint such as /graphql. Servers commonly support POST, and some support GET for queries when it is safe and useful for caching.

Do not assume HTTP status codes carry every application outcome. A well-formed operation that executes can return HTTP 200 and still contain GraphQL execution errors alongside partial data. Parse or validation failures and transport failures use different status handling, so the client must inspect both the HTTP result and the GraphQL response body.

28. When is REST simpler than GraphQL?

REST can be simpler for file downloads, uploads, public cacheable resources, small CRUD APIs, webhook-style integrations, and teams without schema governance. REST also maps naturally to HTTP caching and resource URLs.

That does not make GraphQL bad. It shows judgment. Choose GraphQL when the product has multiple clients, nested data needs, strong schema benefits, or frontend screens that suffer from overfetching, underfetching, and endpoint coordination.

29. How would you debug a slow GraphQL screen?

Start at the user-visible symptom, then split the problem:

  • Inspect which operation ran and which variables changed.
  • Check response size and whether the query selected expensive fields.
  • Check client cache hit/miss behavior.
  • Look for duplicate requests or stale refetch loops.
  • Ask for resolver timing, N+1 traces, backend indexes, and service-call counts.
  • Measure render cost if the data arrives quickly but the screen still feels slow.

A good answer does not blame GraphQL first. It follows the request from component to client cache to network to resolver execution to render.

30. How would you migrate one REST screen to GraphQL?

Choose one screen with clear ownership and measurable behavior. Keep the existing REST flow as a reference, design the GraphQL query around the fields the screen actually renders, generate types, handle loading and error states, compare response size and latency, and verify analytics or logs before removing the old path.

Do not migrate every endpoint just because GraphQL is available. A safe migration proves that the schema, cache, authorization, and observability work for one product flow first.

Code examples interviewers may ask you to reason through

These examples are short on purpose. In an interview, explain the tradeoff around each one instead of only reading the syntax.

Query with variables and a component-owned fragment

fragment ProductCardFields on Product {
id
name
imageUrl
price {
amount
currency
}
}
query ProductGrid($query: String!, $first: Int!, $after: String) {
products(filter: { query: $query }, first: $first, after: $after) {
edges {
cursor
node {
...ProductCardFields
}
}
pageInfo {
hasNextPage
endCursor
}
}
}

What this shows: stable variables, component field ownership, cursor pagination, and a response shape the UI can merge page by page.

Mutation response designed for cache updates

mutation SaveProduct($input: SaveProductInput!) {
saveProduct(input: $input) {
product {
id
isSaved
savedCount
}
userErrors {
field
message
}
}
}

What this shows: the mutation returns the changed entity and fields the UI needs. The client can update a product card, detail page, and saved counter without guessing.

Partial data response

{
"data": {
"product": {
"id": "product_123",
"name": "Everyday Backpack",
"recommendations": null
}
},
"errors": [
{
"message": "Recommendation service timed out",
"path": ["product", "recommendations"]
}
]
}

What this shows: the product page can render core product data while showing a fallback for recommendations. The answer should depend on whether the failed field is critical.

Scenario questions to practice

Use scenarios because they reveal whether the concept survives messy product work. Try answering each prompt in two minutes, then name what you would inspect before choosing a solution.

ScenarioWhat a good answer should reason through
A feed query gets slower as users follow more accountsResolver cost, pagination, batching, query limits, cache policy, and backend indexes
A field cannot be removed because old clients use itDeprecation, schema evolution, operation tracking, and migration windows
A frontend needs partial data with errorsGraphQL response shape, nullable fields, error handling, and UI fallback states
A public GraphQL endpoint is abusedTrusted documents, auth, rate limiting, cost analysis, and monitoring
A mutation updates several visible screensReturn shape, optimistic update, cache write, invalidation, rollback, and refetching

Common weak answers

Each answer below hides the schema, client, or failure decision the interviewer needs to hear. Replace the slogan with the concrete GraphQL tradeoff.

Weak answerWhy it falls shortBetter direction
"GraphQL is always better than REST"The tradeoff depends on clients, caching, team ownership, and server costExplain when GraphQL helps and when REST is simpler
"No overfetching means no performance problem"Resolvers can still do expensive workMention demand control and backend query planning
"Disable introspection and it is secure"Security cannot rely on hiding the schemaUse auth, authorization, operation limits, and monitoring
"Fragments are only for reuse"Fragments also affect cache consistency and component data contractsDiscuss colocated data needs and maintenance
"Types mean the API is safe"Type checks do not prove business permission or runtime availabilityMention auth, nullability, resolver failures, and testing

Answer depth by level

LevelWhat the answer should show
FresherCan write queries and mutations, understands schema basics, variables, loading states, and error states
Mid-levelCan reason about cache updates, pagination, fragments, partial data, and when REST is simpler
SeniorCan discuss schema evolution, resolver cost, N+1, security, observability, generated types, and migration strategy
Staff/leadCan design GraphQL boundaries across teams, define governance, protect the API from expensive operations, and keep client contracts sane

Worked example: product listing with GraphQL

A product listing page is a useful GraphQL interview example because it touches schema design, client state, pagination, caching, authorization, and performance. A shallow answer says GraphQL prevents overfetching. A stronger answer explains the data contract and the cost of each field.

Start with the schema shape:

type ProductConnection {
edges: [ProductEdge!]!
pageInfo: PageInfo!
totalCount: Int
}
type ProductEdge {
cursor: String!
node: Product!
}
type Product {
id: ID!
name: String!
imageUrl: String
price: Money!
inventoryStatus: InventoryStatus
}
type Query {
products(
filter: ProductFilterInput
sort: ProductSortInput
first: Int!
after: String
): ProductConnection!
}

Then explain the frontend flow:

  1. Keep search, filter, and sort in the URL so refresh and sharing work.
  2. Pass filter values as variables, not string-built query text.
  3. Use cursor pagination and merge pages by stable product ID.
  4. Show loading, empty, partial-error, and retry states without clearing safe old data too early.
  5. Ask whether expensive fields such as inventory, discounts, or recommendations are batched and observable.
  6. Keep authorization server-side, especially for fields like wholesale price or admin-only inventory detail.

A good spoken answer might be:

I would query products with filter, sort, first, and after variables. Product cards would own a fragment for id, name, image, price, and inventory status. I would keep filters in the URL, merge cursor pages by product ID, and show a local fallback if a non-critical field fails. Before shipping, I would check resolver timing for inventory and recommendation fields because one GraphQL request can still trigger expensive backend work.

When practicing, make one answer concrete enough to draw: the operation, response shape, cache entries affected, error state, and server check. That exposes missing reasoning faster than another definition drill.

相关文章

REST API Interview Questions for Frontend Devs: 30 Questions (2026)Prepare for REST API interview questions as a frontend fresher with answers on HTTP methods, status codes, fetch, CORS, auth, caching, pagination, errors, and API contracts.
Best Large Open Source Next.js Projects to StudyUnderstand how large scale web apps are structured by studying these Next.js projects.
Databricks Frontend Interview Questions: Prep Guide for 2026Prepare for Databricks frontend interviews with practical questions, official round expectations, CoderPad tips, and frontend system design practice.
JavaScript at Scale
JavaScript at Scale
Dec 21, 2023
标签
How thousands of engineers at big tech companies write JavaScript.
Best Big Companies for a Fulfilling Front End CareerDiscover the best big tech companies for a great career as a Front End Engineer.