The question behind GraphQL vs REST

Free preview 4 min to read

Someone in a planning meeting says "we should move to GraphQL". Nobody in the room wants to be the person who says no to a newer thing, so the team spends a quarter on it. Eighteen months later, there are two ways to read a Course out of the same table, and neither can be deleted.

That's the failure this course is about. GraphQL isn't bad. The failure is GraphQL adopted by a team that didn't have the problem it solves.

The honest default

For most Rails teams the answer is no, and a senior engineer should be able to say that in a room without sounding like a reactionary.

Here's the short version; the rest of the course is the long one. GraphQL exists to let a client you don't control ask for the shape of data it needs. If your application renders HTML on the server and ships it over Turbo, there's no such client. The browser doesn't ask for fields. It asks for a page, and your controller already knows what goes on that page.

This application is mostly that case. It's Hotwire-first: the server renders the page and Turbo swaps fragments of it. The JSON it serves is a small, versioned partner API (learners, certificates and activity under partners/api/v1), a few endpoints behind the code exercises and a user-preferences endpoint. It also sends JSON webhooks out to partners. Every one of those has a known consumer and a fixed shape. Adopting GraphQL here would mean building a second, parallel way to get data out of the same models, for clients that never asked for one.

The condition that flips the answer

The answer stops being no under a specific condition, and that condition isn't "we have an API". It's this: several heterogeneous clients that you don't control, or can't deploy in lockstep with the server.

A mobile app in an app store is the clearest example. You ship version 4.2 today, and some of your users are still on 3.9 next March, because updating is their decision, not yours. Third-party developers on your public API have the same shape. So do four front-end teams shipping four surfaces on their own release trains.

When that's true, "add a field to the endpoint" stops being a one-line change. Letting each client state its own needs starts earning its cost.

What this course covers

Lesson 2 makes the case for GraphQL properly. It covers what over-fetching and under-fetching cost in practice, why one round trip for a whole graph matters on a bad mobile connection, and the precise client condition that makes it worth it.

Lesson 3 is the bill. N+1 becomes the default instead of the exception, and HTTP caching largely disappears. Nothing bounds a query's cost, authorization moves down to the field and errors arrive with a 200.

Lesson 4 is what REST quietly gives you, which teams only notice once they've left. That means cache keys, URLs in your logs and your APM, simple authorization and a versioning story that already exists.

Lesson 5 is the middle ground, which is usually the right answer: sparse fieldsets, a few composite endpoints for the screens that need them, or a backend-for-frontend.

Lesson 6 covers the Rails specifics. It shows how graphql-ruby fits, why a single POST endpoint skips most of Rails' HTTP machinery and what batching and complexity limits look like. It also shows how trusted documents claw back some of what you lost. It carries the coding challenge.

Lesson 7 is the decision framework, ending where this lesson started.

Before any of that

Go and find out what your clients are: not what the roadmap says they might be in two years, but what they are today. How many are there, who controls their deploy schedule, and how many screens are blocked on a round trip you can't avoid?

That inventory decides this, and almost nothing else does.

Lesson 1 of 7 · free

Keep going with lesson 2

What GraphQL actually solves

How over-fetching and under-fetching form one trade, and the three conditions under which GraphQL pays off.

A free account also gives you the quizzes, your progress and notes, and the discussion.

Type to start searching...