FSD Frontend System Design

Part I β€” The Pipes Β· Lesson 1.6

GraphQL

In one lineOne endpoint, one round trip, and the client declares exactly which fields it needs.

Where you've seen itThe Facebook news feed β€” one query returns posts, their authors, and comment counts in a single response shaped like the UI.

  • Time16 min
  • DiagramREST 3 round trips vs GraphQL 1 round trip
  • Chapter1 Β· Networking

Diagram

diagram
REST β€” 3 round trips, and each returns more than the screen shows

  Client                          Server
    │── GET /user/42 ────────────►│   returns 24 fields, UI uses 2
    │◄───────────────────────── ──│
    │── GET /user/42/posts ──────►│   RTT 2
    │◄─────────────────────────── β”‚
    │── GET /posts/*/comments ───►│   RTT 3
    │◄─────────────────────────── β”‚
    total: 3 Γ— RTT + wasted bytes


GraphQL β€” 1 round trip, exactly the fields requested

  Client                          Server
    │── POST /graphql ───────────►│  β”Œ resolver: user
    β”‚   { user(id:42) {           β”‚  β”œ resolver: posts
    β”‚       name                  β”‚  β”” resolver: comments
    β”‚       posts(first:10) {     β”‚
    β”‚         title               β”‚
    β”‚         comments { count }  β”‚
    β”‚   } } }                     β”‚
    │◄── exact shape requested ───│
    total: 1 Γ— RTT, no over-fetch
diagram
THE COST THAT MOVED, NOT DISAPPEARED

  REST     : many endpoints  Β·  free HTTP cache  Β·  over-fetch
  GraphQL  : one endpoint    Β·  no HTTP cache    Β·  N+1 resolver risk
                                (you build a normalized client cache instead)

How it works

  1. The server publishes a schema β€” types, fields, and their relationships.
  2. The client sends a query describing the exact tree of fields it wants.
  3. Resolvers fetch each field; nested fields resolve recursively.
  4. The response mirrors the query shape one-to-one β€” no guessing, no unused fields.
  5. Mutations write; subscriptions stream updates over WebSocket.
graphql
query Feed {
  user(id: 42) {
    name
    posts(first: 10) { title comments { count } }
  }
}

Trade-offs

Use whenAvoid when
Many clients need different field setsOne client, stable payloads
Deeply nested, relational UI dataYou depend on CDN/HTTP caching
Mobile bandwidth actually mattersSmall team, no resolver-perf ownership

Two traps to name in an interview: the N+1 problem (fix with DataLoader batching) and unbounded query depth (fix with depth limits, complexity scoring, and persisted queries).

Interview angle

"GraphQL removed over-fetching. What did it cost you?"

  • HTTP caching: POST /graphql is opaque to CDNs, so caching moves into the client (normalized store) or needs persisted queries + GET.
  • Server performance becomes the client's problem β€” one careless nested query can hammer the database.
  • You now own schema versioning, deprecation, and query governance.

Recap

  • Client declares the shape; server resolves it in one round trip.
  • Over-fetching and round trips go away; caching and query governance arrive.
  • Say "N+1" and "persisted queries" β€” that's the senior signal.