Almost every web or mobile app talks to a server through an API, and two styles dominate: REST and GraphQL. The debate is often framed as old versus new, but the real question is which fits your data, your team and your clients. If you are new to APIs, read what an API is first.
Key takeaways
- REST: many URLs, fixed responses, simple, cacheable.
- GraphQL: one endpoint, client-defined responses, flexible, strongly typed.
- Choose REST for simple resources and public APIs, GraphQL for rich, nested data and varied clients.
- You can use both.
How REST works
REST organises an API around resources with their own URLs and uses standard HTTP methods:
GET /api/v1/users/42 # one user
GET /api/v1/users/42/orders # that user's orders
POST /api/v1/orders # create an order
PATCH /api/v1/orders/9 # update an order
DELETE /api/v1/orders/9
Each endpoint returns a predefined JSON shape. Status codes describe the result (200, 201, 404, 429…).
How GraphQL works
GraphQL has a single endpoint, usually /graphql, and a typed schema. The client sends a query describing exactly which fields it needs:
query {
user(id: 42) {
name
orders(last: 3) {
id
total
items { title }
}
}
}
The server returns only those fields, in the same shape as the query. Changes use mutations, and live updates use subscriptions.
The classic problem GraphQL solves
Over-fetching: the endpoint returns 40 fields but the screen needs 3. Under-fetching: the screen needs a user, their orders and the order items, which takes three round trips with REST. GraphQL lets the client ask for all of it in one request, which matters on mobile networks.
Side-by-side comparison
| Factor | REST | GraphQL |
|---|---|---|
| Endpoints | Many, one per resource | One |
| Response shape | Defined by the server | Defined by the client query |
| Learning curve | Low | Medium |
| Caching | Easy with HTTP caching and CDNs | Harder; needs client or persisted-query strategies |
| Versioning | URL or header versions (/v1, /v2) | Evolve the schema; deprecate fields |
| Typing and docs | Optional (OpenAPI/Swagger) | Built in: the schema is the documentation |
| File uploads | Straightforward | Needs extra conventions |
| Tooling | Huge ecosystem and simple debugging with curl | Excellent dev tools (explorers, code generation) |
| Real-time | Webhooks, SSE, WebSockets | Subscriptions |
| Error handling | HTTP status codes | Usually 200 with an errors array |
Performance and security considerations
REST
- Cache with ETags and CDNs.
- Paginate lists and limit fields where needed.
- Rate limit per endpoint.
GraphQL
- N+1 queries: a nested query can trigger many database calls. Use batching tools such as DataLoader.
- Query cost: clients can ask for deeply nested, expensive data. Set depth and complexity limits and timeouts.
- Authorisation per field: check permissions in resolvers, not only at the endpoint.
- Introspection: consider disabling it in production for private APIs.
- Persisted queries can improve caching and security.
For both, follow the API security basics in our API guide: HTTPS, authentication, validation and rate limits.
When to choose REST
- Your data maps cleanly to resources (products, users, orders).
- You are building a public or partner API that must be easy to learn and cache.
- Your team is small and wants the shortest path to production.
- You use CDNs heavily for read traffic.
When to choose GraphQL
- Several clients (web, iOS, Android, partners) need different shapes of the same data.
- Your data is highly connected and screens combine many entities.
- Front-end teams want to move fast without waiting for new endpoints.
- You want a strongly typed contract and generated types.
Practical hybrid approaches
- REST for simple resources, authentication and file uploads; GraphQL for complex read queries.
- A backend-for-frontend layer that exposes GraphQL to the website over existing REST services.
- Start with REST; add GraphQL when you feel the pain of over-fetching and many round trips.
Our own stack for many projects is a REST API built with NestJS and Prisma behind a Next.js front end, which is a great fit for dashboards and content sites. See why Next.js suits business websites and how to build a SaaS MVP.
Decision checklist
- How many different clients need this data?
- How nested is the data, and how often do screens need several entities at once?
- Does HTTP caching matter for your traffic?
- What does your team already know?
- Is this API public, where simplicity and documentation matter most?
Need help designing an API? Talk to our engineers or get in touch.



