BackendLesson 3 of 48 min

REST, GraphQL, and RPC

Three styles, three different things being optimised. None of them is a religion.

These are three ways of organising the same conversation. The differences come down to who decides what data is returned, and how many round trips a screen needs.

REST, organised by thing

  • Endpoints are nouns: /users, /orders
  • The server decides what each returns
  • Very cacheable, very simple to inspect
  • A rich screen may need several calls

GraphQL, organised by question

  • One endpoint; the client describes what it wants
  • One round trip can fill a whole screen
  • No over-fetching of unused fields
  • Caching and rate limiting get much harder

RPC is the third style and the most direct: instead of modelling nouns, you call a named function on the server as though it were local. This app is built that way: a server function is RPC with the network plumbing and type checking generated for you.

A reasonable default: RPC or server functions for your own frontend, REST for public APIs other people build against. Reach for GraphQL when you genuinely have many different clients wanting many different slices of the same data, which is a real problem but a less common one than the discourse suggests.

What to remember

  • REST organises by resource, GraphQL by query, RPC by action.
  • RPC with shared types is a strong fit for your own frontend.
  • Public APIs benefit from REST’s predictability and cacheability.

Terms in this lesson

Field notes

Loaded from a deliberately slow source. The lesson above was already readable while this was still travelling. That is streaming, and it is the same trick a chat interface uses.

The URL that read everyone’s invoices

An invoice page checked that you were logged in and then loaded whatever id was in the address. Changing the number showed somebody else’s invoice. It was found by a customer who mistyped, not by a review.

Classic IDOR, still extremely common

The key in the client bundle

An API key was placed behind the public environment prefix so it would be readable from the frontend. It worked. It was also visible to every visitor, and was being used by strangers within a week.

Scraped from a public bundle

resolved in 901ms · region iad1

Hide field notes toggles a search param the loader reads. With it off, the slow promise is never created, so nothing streams.