OpenAPI vs GraphQL
OpenAPI and GraphQL describe two different styles of API, so the choice is about how clients fetch data rather than which is newer. OpenAPI documents a REST/HTTP API: its paths, the methods on each path, parameters, request and response bodies, status codes and security schemes, written as a YAML or JSON document. GraphQL takes the opposite approach — its schema definition language (SDL) defines a single typed graph, and clients send queries to one endpoint asking for exactly the fields they need, so the contract describes types and relationships instead of URLs and verbs. Choose OpenAPI when you are building or documenting conventional REST services, want HTTP-native caching and the broadest tooling, or need to describe existing endpoints. Choose GraphQL when clients need flexible, precise fetching across related types and you want a strongly typed contract the server enforces at runtime. Many teams run both: REST for coarse public resources, GraphQL for the data-hungry app layer.
| Dimension | OpenAPI | GraphQL |
|---|---|---|
| Describes | A REST/HTTP API: paths, methods, bodies | A typed graph of data and operations |
| Endpoints | Many URLs, one per resource/operation | One endpoint; the query selects the data |
| Data fetching | Server defines each response shape | Client asks for exactly the fields it needs |
| Schema written in | YAML or JSON (OpenAPI 3.x / Swagger 2.0) | GraphQL SDL (its own type language) |
| HTTP caching | Native: cache by URL, status codes, verbs | Mostly POST to one URL; cache at the field/client layer |
| Versioning | Often new paths or a version prefix | Evolve the graph; add fields, deprecate old ones |
| Typical home | Public/partner APIs, CRUD, integrations | Product APIs with rich, interrelated data |
API style: endpoints vs a typed graph
The deepest difference is what the contract describes. An OpenAPI document is a catalogue of HTTP operations: each path (such as /users/{id}) lists the methods it supports, the parameters and request body each accepts, and the response bodies and status codes it returns. The shape of every response is decided by the server, and a client composes a screen by calling several endpoints. A GraphQL schema, by contrast, describes a single typed graph — object types, their fields, and how they relate — exposed through one endpoint. The client sends a query that walks that graph and names exactly the fields it wants, and the server returns a response matching the query. So OpenAPI answers "what endpoints exist and what does each return?", while GraphQL answers "what types and relationships exist, and what does this particular client want from them right now?". That reframing, from fixed endpoints to a queryable graph, is the heart of the decision.
Data fetching: over- and under-fetching
Because a REST response shape is fixed by the server, a client often receives fields it does not need (over-fetching) or has to call several endpoints to assemble one view (under-fetching, sometimes called the N+1 round-trip problem). Teams work around this with query parameters, sparse fieldsets, or purpose-built composite endpoints, but those are conventions layered on top of OpenAPI, not part of it. GraphQL addresses the same problem in the protocol itself: a single query selects precisely the fields required across many related types and returns them in one round trip, so the front end can evolve its data needs without new endpoints or server changes. The trade-off is that flexible client queries shift complexity onto the server, which must guard against expensive or deeply nested requests with depth limits, query cost analysis or persisted queries. OpenAPI keeps response shapes predictable and easy to reason about; GraphQL trades that predictability for client-driven precision.
Caching, versioning & evolution
OpenAPI/REST is HTTP-native, and that pays off in caching and evolution. A GET request to a stable URL can be cached by browsers, CDNs and proxies using ordinary HTTP cache headers, and idempotent methods and status codes behave the way the whole web infrastructure expects. Versioning is usually explicit — a new path, a /v2/ prefix, or a media-type version. GraphQL typically sends queries as POST to a single URL, so URL-based HTTP caching does not apply out of the box; caching happens at the client (normalised caches keyed by object identity) or via persisted queries and edge tooling. In exchange, GraphQL favours continuous evolution: you add fields and types freely and mark old ones with the @deprecated directive rather than minting a new version, because clients only receive the fields they ask for. Neither model is strictly better — REST leans on mature HTTP caching, GraphQL leans on additive, deprecation-driven schema growth.
Tooling & ecosystem
Both have deep ecosystems pointed at different problems. OpenAPI underpins a vast REST toolchain: documentation renderers like Swagger UI and Redoc, client and server code generators across most languages, mock servers, contract testing, and API gateways that read the spec directly — and because it builds on plain HTTP, it interoperates with everything that already speaks HTTP. GraphQL's ecosystem centres on the typed graph: schema-aware IDEs and explorers, client libraries with normalised caching and subscriptions for live data, schema-stitching and federation for composing multiple services into one graph, and server frameworks that enforce the SDL at runtime. The pragmatic question is which world your clients and infrastructure already live in: if you are describing or consuming HTTP endpoints and want maximal interoperability, OpenAPI is the native tool; if you are serving a typed graph to flexible clients, GraphQL is.
Which should you choose?
Choose OpenAPI when you are documenting or building a REST/HTTP API — public or partner APIs, CRUD services, third-party integrations — and you want HTTP-native caching, status codes and the broadest client and gateway tooling, or simply need to describe endpoints that already exist. Choose GraphQL when a typed graph with client-driven fetching is the priority: product APIs with rich, interrelated data, many distinct client views, and a front end that should evolve without waiting on new endpoints. Many architectures use both — REST for coarse, cacheable resources and GraphQL for the application layer. When you have decided, check your contract with the right tool: validate your OpenAPI document against OpenAPI 3.x or Swagger 2.0, or validate your GraphQL SDL to confirm the schema parses. Both run entirely in your browser, so nothing you paste leaves your device.
OpenAPI vs GraphQL FAQ
Are OpenAPI and GraphQL mutually exclusive?
No. Plenty of systems run both, and they often divide the work cleanly. A common pattern is REST endpoints described with OpenAPI for coarse, cacheable public or partner resources — file downloads, webhooks, simple CRUD, third-party integrations that expect HTTP verbs and status codes — alongside a GraphQL endpoint for the data-hungry application layer, where a single front end needs to assemble many related entities in one round trip. GraphQL can even sit in front of REST services as an aggregation layer. The two describe APIs at different granularities rather than competing for the same one, so the realistic question is usually which style fits each surface of your system, not which to adopt site-wide.
Does GraphQL replace REST?
Not in general. GraphQL replaces some of the patterns teams used to build by hand on top of REST — multiple endpoints per view, ad-hoc query parameters to shape responses, and bespoke aggregation to avoid over- and under-fetching. For product APIs with rich, interrelated data and many client views, that is a real simplification. But REST described by OpenAPI remains the better fit where HTTP-native semantics matter: response caching by URL, idempotent methods, status codes, range requests, and the enormous ecosystem of gateways, proxies and clients that speak HTTP directly. REST is not legacy; it is a different contract that happens to be the right one for a large class of APIs.