DEV Community

Vivian Voss
Vivian Voss

Posted on • Originally published at vivianvoss.net

GraphQL: The Query Tax

The Invoice — Episode 15

"Query exactly what you need! One endpoint! No over-fetching!"
Splendid. Let us examine what you are actually paying for.

In 2012, Facebook had a problem: hundreds of microservices, a mobile News Feed, constrained bandwidth. They built GraphQL to solve it. The solution was brilliant. For Facebook. You have a REST API with sensible endpoints and a fetch() call. But do carry on.

The N+1 Invoice

Fetch 25 users with their posts. One query fetches users. Twenty-five resolvers fetch posts. That is 26 database queries for one API call. The fix: DataLoader, a batching utility you must implement yourself. It is not built in. It is homework.

Without it, a relation-heavy GraphQL endpoint performs measurably worse than the REST equivalent it was meant to replace.

The Caching Invoice

REST uses HTTP caching: ETags, Cache-Control, CDN layers. GET requests to unique URLs, cacheable by design.

GraphQL uses POST to a single endpoint. Every query, every mutation, one URL. HTTP caching does not work. CDNs cannot cache it. You need Apollo's normalised cache, persisted queries, or custom layers. HTTP has been demoted to a dumb tunnel.

56% of teams report caching challenges with GraphQL. One rather suspects the other 44% have not noticed yet.

The Security Invoice

A 128-byte nested query can consume 10 seconds of CPU time. No authentication required. Recursive relationships allow depth that REST never exposes.

80% of GraphQL APIs are vulnerable to denial-of-service through query depth. Most frameworks ship with no default depth limit. You must build: depth limiting, cost analysis, complexity-based rate limiting. Traditional rate limiting by endpoint does not work when every request hits the same URL.

The Monitoring Invoice

GraphQL returns HTTP 200. Always. Even when your application is on fire. Errors live in a JSON array inside the response body. Your dashboards show 100% success. Your users see failures. Marvellous.

The Alternative

REST with OpenAPI 3.0: self-documenting, typed client generation, HTTP caching built in. fetch() ships with every browser at 0 KB. Apollo Client adds 43 KB.

GraphQL solves a real problem: aggregating hundreds of services behind a single query interface. If you have that problem, use it. If you do not, you are paying the invoice for someone else's architecture.

The Pattern

Facebook built GraphQL for a mobile feed consuming hundreds of services over constrained bandwidth. You copied it for a dashboard with a handful of endpoints. The query language is excellent. The question is whether you have queries worth asking.

Read the full article on vivianvoss.net →


By Vivian Voss — System Architect & Software Developer. Follow me on LinkedIn for daily technical writing.

Top comments (0)