Skip to content

Instantly share code, notes, and snippets.

@SystemDisc
Created March 31, 2026 23:14
Show Gist options
  • Select an option

  • Save SystemDisc/8f32f5bae18c7ba0163ec57037ba4ea5 to your computer and use it in GitHub Desktop.

Select an option

Save SystemDisc/8f32f5bae18c7ba0163ec57037ba4ea5 to your computer and use it in GitHub Desktop.
GraphQL Is Never the Right Option

Argument

There are always better modern alternatives to GraphQL for any given real-world use case in software development.

1. Define "better"

A better API option is one that:

  1. meets the functional requirement,
  2. uses established standards,
  3. preserves normal HTTP or RPC infrastructure,
  4. keeps contracts machine-discoverable,
  5. stays explicit about resources or operations, and
  6. avoids introducing a separate query language and execution model unless that is strictly necessary.

That definition is not vague. It is a concrete engineering ranking function for modern software.

2. State the relevant facts

OpenAPI already standardizes machine-discoverable HTTP API contracts and is explicitly meant to let both humans and computers discover and understand a service's capabilities with minimal implementation logic. (OpenAPI Initiative Publications)

JSON:API already standardizes a resource-oriented wire format and is explicitly designed to minimize both request count and transmitted data while preserving readability, flexibility, and discoverability. It also standardizes relationship inclusion and sparse fieldsets. (JSON:API)

Connect already standardizes typed RPC over HTTP. It is designed for browser- and gRPC-compatible HTTP APIs, generates type-safe clients, and runs on ordinary HTTP infrastructure rather than inventing a separate application query model. (Protobuf RPC that works)

GraphQL standardizes a different thing: a separate query language and execution model built around hierarchical selection sets, aliases, introspection, and a response model that can return both data and errors from a single operation. That is real capability, but it is also extra protocol surface and extra execution semantics. (GraphQL Specification)

3. Partition the real-world problem space

Every real API use case in modern software falls into one of three buckets.

1. Resource-oriented retrieval

If the problem is fetching data and related data, use standard HTTP APIs described by OpenAPI, optionally with JSON:API-style inclusion and sparse fieldsets. That already covers discoverability, resource relationships, and payload shaping without adding a separate query language. (OpenAPI Initiative Publications)

2. Actions, commands, and workflows

If the problem is "do something" rather than "traverse a graph," use typed RPC. Connect is a direct fit here: explicit procedures, generated clients, ordinary HTTP transport, and strong typing without inventing a general-purpose client query language. (Protobuf RPC that works)

3. UI-specific composition

If the problem is that one screen or consumer needs a custom aggregate shape, use a BFF or read model. Shape the data server-side with explicit resources or operations instead of turning the whole API into a client-driven graph query system.

That makes the space exhaustive: every supposed GraphQL use case is either a resource problem, an operation problem, or a composition problem.

4. Why GraphQL loses under this decision rule

GraphQL's distinctive value is not "typed APIs" or "discoverability" in general. OpenAPI, JSON:API, and Connect already cover those needs in standards-aligned ways. GraphQL's distinctive value is specifically its separate query language and execution model: hierarchical selection, aliases, introspection, and field-by-field execution semantics. (GraphQL Specification)

Under the definition of "better" above, that distinctive value is not a benefit unless it is strictly necessary. If the same real-world requirement can be satisfied with standard HTTP resources, standard RPC methods, or explicit server-side composition, then GraphQL's extra language and execution model are overhead, not value.

So the decision rule is simple:

  • If resources are enough, use resource APIs.
  • If operations are enough, use RPC.
  • If aggregation is needed, compose on the server.
  • Do not introduce a general-purpose client query language unless nothing else can meet the requirement.

Once stated that way, GraphQL is dominated in practice.

5. Apply the strongest pro-GraphQL example

The strongest real-world defense of GraphQL is usually a GitHub-style public graph API. GitHub itself says GraphQL is more flexible for integrators, lets clients define precisely the data they want, and can replace multiple REST requests with a single call. (GitHub Docs)

That still does not make GraphQL the best option.

It shows only that GraphQL is viable. The underlying requirement is still one of these:

  1. resource retrieval with relationships,
  2. explicit operations over connected entities, or
  3. server-side composition for consumer-specific shapes.

All three can be handled with standards-based HTTP and RPC approaches plus explicit composition. Under a standards-first, infrastructure-first decision rule, "can replace multiple REST calls with one GraphQL call" is not enough to win, because fewer calls alone is not the top criterion. Preserving normal infrastructure, explicit contracts, and avoiding a separate query language rank higher.

So even the strongest real-world GraphQL example does not overturn the doctrine. It only shows that some teams accept the trade.

6. Final conclusion

The full argument is:

  1. Better API designs for modern software are standards-based, infrastructure-aligned, machine-discoverable, explicit, and avoid extra protocol machinery unless strictly necessary.
  2. OpenAPI, JSON:API, and Connect already cover the modern API problem space for resources, relationships, payload shaping, typed operations, and client generation. (OpenAPI Initiative Publications)
  3. GraphQL's distinguishing feature is a separate query language and execution model with its own semantics and operational costs. (GraphQL Specification)
  4. Any real-world GraphQL use case can be recast as resource retrieval, explicit operations, or server-side composition.
  5. Therefore, for any real-world use case in modern software, there is always a better modern alternative to GraphQL.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment