gitGood.dev
Back to Blog

Top 50 GraphQL Interview Questions in 2026 (With Real Answers)

P
Pat
13 min read

Top 50 GraphQL Interview Questions in 2026 (With Real Answers)

A few years ago, the conventional wisdom was that GraphQL had peaked. The 2026 reality is more interesting: GraphQL didn't take over the world, but it did become the default for any company with multiple frontend clients (web, iOS, Android, partners) hitting one backend graph. Federation matured. Persisted queries became standard. And the interview bar got real.

Here are the 50 questions that come up in GraphQL-heavy interview loops at companies running it in production.


Fundamentals (1-10)

1. What is GraphQL and what problem does it solve?

A query language and runtime for APIs where the client specifies the exact shape of the response. Solves over-fetching (REST endpoints returning fields you don't need) and under-fetching (REST requiring N round trips for related data).

2. GraphQL vs REST in one paragraph.

REST exposes resources at URLs with fixed shapes. GraphQL exposes a single endpoint and a typed schema that clients query against. REST scales better with HTTP caching and CDN. GraphQL scales better with diverse clients and fast iteration. Most companies use both - REST for public APIs and edge-cacheable reads, GraphQL for product surfaces.

3. What are the three operation types?

Query (read), Mutation (write), Subscription (real-time stream, typically over WebSocket or Server-Sent Events).

4. What's a resolver?

A function that produces the value for a single field. The resolver tree maps to the query tree. Each field has its own resolver, called with (parent, args, context, info).

5. Explain the type system.

Scalars (Int, Float, String, Boolean, ID), Object types (with fields), Interface, Union, Enum, Input, and List/Non-Null wrappers. The schema is the contract; clients can introspect it (or not, in production).

6. What's the difference between Interface and Union?

  • Interface: a contract of fields that implementing types share. Useful when types share fields.
  • Union: a set of possible types with no shared fields. Resolved with __typename.

SearchResult = Article | Video | User is a union. Node with id: ID! is an interface.

7. What does ! mean?

Non-null. String! means the field must return a non-null string. [String!]! means a non-null list of non-null strings. Non-null in the response is a strict contract: if a non-null field errors, that error propagates up to the nearest nullable parent (or the whole query, if everything is non-null).

8. What is null bubbling?

The propagation mentioned above. A null in a non-null field bubbles up until it hits a nullable parent. Critical to design schemas where nullability matches reality - over-using ! makes single-field failures kill whole queries.

9. How does GraphQL handle versioning?

It doesn't, in the REST sense. You evolve the schema by adding fields, deprecating old ones with @deprecated(reason: "..."), and removing them after clients migrate. Tools like graphql-inspector track schema diffs in CI.

10. What's introspection and should you disable it in production?

Introspection lets clients query the schema itself (__schema, __type). Useful in dev. In production, you typically disable it for unauthenticated traffic to avoid exposing your full surface area. Authenticated internal tools can still introspect.


Schema Design (11-20)

11. Walk me through how you'd design a schema for a paginated post feed.

type Query {
  feed(first: Int!, after: String): PostConnection!
}

type PostConnection {
  edges: [PostEdge!]!
  pageInfo: PageInfo!
}

type PostEdge {
  node: Post!
  cursor: String!
}

type PageInfo {
  hasNextPage: Boolean!
  endCursor: String
}

The Relay Connection spec - edges, node, cursor, pageInfo. It's verbose but it's standard, tooling supports it, and it correctly handles pagination edge cases.

12. Cursor vs offset pagination - which and why?

Cursor. Offset pagination breaks when items are inserted/deleted, gets slow at deep pages, and produces duplicate or missing items. Cursor pagination is stable, performant, and the standard for GraphQL.

13. Why use Connection types instead of just returning [Post!]!?

Future-proofing. Connections give you a place for pageInfo, totalCount, and other metadata without breaking clients. Even if you don't need those today, the shape lets you add them.

14. How do you model errors?

Three options:

  • Top-level errors array (default GraphQL): generic, no typing.
  • Errors as Union types in mutations: signUp(...): SignUpResult! where result is User | EmailTaken | WeakPassword. Strongly typed, clients get exhaustiveness.
  • Custom error extensions: errors[*].extensions.code = 'NOT_FOUND'. Pragmatic middle ground.

The 2026 best practice is the union approach for mutations. Clients can pattern match on error types in TypeScript with full type safety.

15. What's an Input type and why does it exist?

Object types are output-only. Input types are for arguments to fields/mutations. They prevent ambiguity - the schema clearly distinguishes "things you send" from "things you receive."

16. How do you model authorization in the schema?

Don't model it as schema-level types. Authorization is enforced in resolvers (or in field-level directives like @auth). Two patterns:

  • Field nulling: unauthorized fields return null.
  • Field erroring: unauthorized fields throw.

Pick consistently. Inconsistency confuses clients.

17. How would you handle file uploads?

Three options:

  • multipart/form-data with the GraphQL multipart spec. Works but has overhead.
  • Direct upload to S3 with signed URLs - server returns the URL, client uploads, sends back the resulting key. The 2026 default.
  • Base64 in the mutation - never. Bloats payload, breaks caching.

18. When do you use a custom scalar?

For values that have a specific shape but don't have a built-in - DateTime, EmailAddress, JSON, URL. Custom scalars enforce serialization/parsing rules at the gateway. The graphql-scalars package gives you most of them.

19. Schema-first vs code-first - which?

Schema-first (.graphql files, codegen): gives you a single source of truth that non-engineers can read. Better for cross-team APIs.

Code-first (Pothos, TypeGraphQL, Nexus): better type safety inside the codebase, harder for non-TS teams to read.

In 2026, code-first with Pothos is winning in TypeScript shops. Schema-first still wins in polyglot environments.

20. How do you avoid breaking changes?

A breaking change is anything that removes or renames a type/field, changes a nullable to non-null in input, or non-null to nullable in output. Process: deprecate first, monitor usage with persisted query analytics, remove only after all clients migrate. CI tools like graphql-inspector catch breaking changes in PRs.


Resolvers and Performance (21-30)

21. What is the N+1 problem?

A query that resolves a list, then resolves a related field for each item, hitting the database once per item. 100 posts → 1 query for posts + 100 queries for authors = 101 queries.

22. How do you fix N+1?

DataLoader. It batches and caches calls within a request. The resolver for post.author calls authorLoader.load(post.authorId); DataLoader collects all loads in the tick, fires one batched DB call, returns results in order.

23. Show me a basic DataLoader.

const authorLoader = new DataLoader(async (ids: readonly string[]) => {
  const authors = await db.user.findMany({ where: { id: { in: [...ids] } } });
  const byId = new Map(authors.map(a => [a.id, a]));
  return ids.map(id => byId.get(id) ?? null);
});

// in resolver
Post: { author: (post, _args, ctx) => ctx.loaders.author.load(post.authorId) }

The order of returned values must match the order of input keys.

24. When does DataLoader caching bite you?

It caches per-request. If a resolver mutates data and another resolver re-reads it in the same request, the second read returns the stale cached value. Clear or scope loaders carefully on mutations.

25. Should you put DataLoader in context?

Yes. New loaders per request. Sharing loaders across requests is a memory leak and a stale-data bug.

26. What is query cost analysis?

Estimating the cost of a query before executing it. Without it, a malicious client can request users { posts { comments { author { posts { ... } } } } } and DOS your DB. Tools: graphql-cost-analysis, graphql-query-complexity. Reject queries above a budget.

27. What's query depth limiting?

Reject queries deeper than N levels. Cheap defense, complements cost analysis. Five to seven levels is typical.

28. What is persisted queries?

Clients send a hash of a known query. The server has the hash → query mapping. Benefits: smaller requests, blocks unknown queries (anyone sending a raw query is rejected), enables CDN caching of GET requests. Apollo, Relay, and most modern stacks support it.

29. How does persisted queries enable CDN caching?

GET requests with the persisted query hash + variables are deterministic and cacheable. CloudFront/Fastly cache them. Public, anonymous reads (e.g., a marketing page query) get edge-cached for milliseconds.

30. What is @defer and @stream?

Directives that let the server send a partial response immediately and stream the rest. @defer for delayed fragments, @stream for items in a list. Lets a fast field return while a slow related field comes later. Browser support and tooling matured in 2024-2025; expect questions in 2026.


Federation and Architecture (31-40)

31. What is GraphQL Federation?

Multiple subgraphs (separate services, each with their own schema) composed into one supergraph by a router/gateway. Each subgraph owns its types and entities. Replaces the "schema stitching" approach.

32. What's an entity in Federation?

A type that can be referenced across subgraphs, identified by a @key directive. Example: User @key(fields: "id"). Other subgraphs extend User to add fields they own.

33. Walk me through a federated query.

Client sends one query. Router parses it, plans which subgraphs need to resolve which parts, fans out, stitches the results, returns one response. The Apollo Router (Rust) is the dominant gateway in 2026.

34. When does Federation make sense?

When you have multiple teams owning distinct domains and a single graph for clients. Don't reach for it on day one - one team, one service is fine. The complexity only pays off at multi-team scale.

35. Federation v1 vs v2 - what changed?

V2 added composition rules that catch more errors at supergraph build time, removed the extend keyword requirement, added @shareable, @external, and @override for clearer ownership semantics. By 2026 everyone is on v2.

36. What is @shareable and when do you use it?

A field that's shared (same value) across subgraphs. Without @shareable, a field defined in two subgraphs is a composition error. With it, the gateway can choose either source. Use sparingly - it usually means the type isn't actually one team's.

37. How do you do auth across a federated graph?

Two layers: gateway-level auth (validate JWT, extract identity, inject into headers) and subgraph-level auth (each subgraph enforces its own rules using the trusted identity). Don't trust the request body in subgraphs - only headers from the gateway.

38. How does observability work for GraphQL?

Tracing per resolver, per query. Apollo Studio, Hive, or open-source (graphql-yoga + OpenTelemetry). Surface: query count, p95 latency by operation name, resolver-level latency, error rate by field, persisted query coverage.

39. What's the right way to log a slow GraphQL query?

By operation name (the named query, not the raw doc). Plus the resolver path that's slow. Logging the full query is sometimes useful but spammy - use sampling.

40. How do you handle backwards compatibility in a federated graph?

Same as a single graph - deprecate and remove. The harder part is coordinating across teams. Tools like Apollo's "schema checks" run client query traffic against proposed schema changes in CI to flag breaks before merge.


Production Concerns (41-50)

41. How do you secure a public GraphQL endpoint?

  • Disable introspection or restrict to authenticated principals.
  • Persisted queries only (block unknown queries).
  • Cost analysis and depth limits.
  • Rate limiting per principal and per operation.
  • Auth at field/resolver level for sensitive fields.
  • Strict CORS.
  • Field-level auditing on PII reads.

42. How do you cache GraphQL responses?

Three layers:

  • Client cache (Apollo Client, Relay): normalized cache by ID.
  • HTTP cache (CDN): persisted queries + GET makes this work.
  • Server-side cache (Redis): cache resolver results, especially for data joins.

GraphQL's "single endpoint" makes naive HTTP caching hard, but the persisted-query path solves it.

43. What is Relay's normalized cache?

Apollo Client and Relay store entities by ID, not by query. When User:123 is updated by any query/mutation, all UI bound to User:123 re-renders. Requires every entity to have a stable global ID.

44. What's a global object identification (Relay spec)?

Every node has a globally unique ID across the graph. The Node interface with id: ID! and a top-level node(id: ID!): Node field. Lets clients refetch any object by ID and powers normalized caches.

45. How would you implement subscriptions in 2026?

WebSocket via graphql-ws (the modern protocol; subscriptions-transport-ws is deprecated). Or Server-Sent Events for one-way streams. Backend: pub/sub fanout (Redis, Kafka, NATS). Be ready to talk about backpressure and reconnection.

46. What's a common subscription pitfall?

Holding open connections without enforcing auth refresh, leaking memory, or fanning out an event to every connected client when only a subset cares. Always filter subscription resolvers to the authorized scope.

47. How do you test a GraphQL API?

  • Unit tests on resolvers (with mocked context).
  • Integration tests that hit the schema with executeQuery or via supertest against the running server.
  • Snapshot tests for query responses.
  • Contract tests for federated subgraphs.
  • Schema diff in CI to catch breaking changes.

48. Apollo Server vs alternatives in 2026?

  • Apollo Server: still the most popular, mature, paid plans for enterprise.
  • GraphQL Yoga: lightweight, Envelop plugin system, popular for federated subgraphs.
  • Mercurius (Fastify): fastest in benchmarks, Node-only.
  • Hot Chocolate (.NET), graphql-java, Strawberry (Python), gqlgen (Go) for non-Node.

The Apollo Router (gateway) is essentially the standard for federation regardless of subgraph framework.

49. When would you NOT pick GraphQL?

  • Public APIs where REST + good docs is more accessible.
  • Mostly-CRUD with one client, where the schema overhead isn't justified.
  • Heavy file streaming or RPC patterns - gRPC fits better.
  • A team that doesn't have time to maintain operational tooling for it.

GraphQL is operationally heavier than REST. Don't pick it for a single small service.

50. You're at a 1000-engineer company with 50 microservices. Should you adopt federation?

Probably yes, but the migration is not free. The right path: start a federated supergraph, migrate the highest-value clients first (mobile is usually the strongest case), let teams onboard subgraphs as they need to expose data. Don't try to "federate everything" - federation pays off where clients need cross-domain queries.


Final Note

GraphQL interview questions in 2026 are heavier on operations, federation, and security than on syntax. The schema design and resolver questions are still common, but the differentiators are: can you talk about persisted queries, cost analysis, federation versioning, and the production failure modes?

Memorize the directives. Understand DataLoader. Know what a Relay Connection looks like cold. And have a strong opinion on errors-as-data vs the default errors array - interviewers want to see you've thought about it.

Ship the offer.