REST vs GraphQL

General information

CRITERIA

REST

GraphQL

Overview

Due to its design REST service puts all heavy lifting of managing data relations on client side. At the same time server forces clients to consume the size & shape of data it determined not concerning of particular need.

GraphQL service takes the heavy lifting of managing data relations on itself, becoming more flexible & adaptive to any possible API consumer. Client side only decides which data size & shape it needs at the moment & receives exactly it.

General Summary

Pros:

  • Easy & fast to set up & see first results (short-term win);

  • A lot of recipes & best practices (error handling, caching, security etc.) due to maturity of the approach;

Cons:

  • Low performance for clients due to overfetching, additional network roundtrips;

  • Less predictable & more error prone for clients due to the fact that type checking & introspection are not mandatory;

  • Harder to maintain & extend, keep in ideologically pure state;

Pros:

  • Flexible to changes & easily adaptive to any possible API consumer (long-term win);

  • Provides better client experience due to network performance;

  • More predictable due to strict type checking & built-in retrospection;

Cons:

  • At the moment may not have mature solutions for widely known problems (error handling, caching, security etc.), which can turn out to reinventing the wheel;

  • Requires more time to set up & learn;

Architecture

  • Endpoint is the identity of a resource. Server determines shape & size of the resource to be sent to client.

  • REST API provides a list of endpoints. Different HTTP verbs as GET, POST, PUT, DELETE, PATCH are used to describe client-server communications.

  • API requests are handled by route handling functions that are matched by URL path & HTTP verb. Result, produced by a function is serialized & sent back to client with appropriate headers & HTTP status codes.

  • Resource is described in GraphQL schema with the help of 'types'. The client is free to decide which & how many data to retrieve at once.

  • GraphQL API only has one endpoint, usually '/graphql'. Additionally, it only takes one HTTP method: POST (there's an option to enable GET too).

  • GraphQL server receives a request with 'query', describing what data is needed. Appropriate resolvers then are called to fulfill each field in a query. The result is combined together & sent back to client.

Authorization

Request level

Field level

Error handling

REST API relies on widely spread http error conventions, which doesn't change significantly from service to service.

Mostly errors occur at request level - the whole request is failed in case of any error.

Field level errors can be implemented additionally on client-server agreement.

GraphQL API uses custom solutions for error handling, which heavily rely on framework that is used & local error handling convention between client & server side. Error handling can differ a lot from service to service.

Errors are added as an additional array in response from server. HTTP statuses are not used.

Both request level errors & field level errors can occur. That means that requested data can be returned partially, because some of the fields can be resolved, but some are not because of error.

Security

Commonly known types of threats that should be handled in REST API:

  • injection attacks,

  • DoS,

  • broken authentication,

  • sensitive data exposure,

  • broken access control,

  • parameter tampering,

  • Man-in-the-middle

  • etc

GraphQL is just a layer, no protection is provided from the box. All the threats that are usual for REST API can occur here as well. Still they can have GraphQL specificity e.g.:

  • Injection attacks can be caused by not properly sanitized query fields

  • DoS: deep queries can consume all server resources; complex queries can add additional load on database. As an approach query depth limiting & query cost analysis can be added;

Ecosystem

REST service has a large amount of frameworks for back-end side, no need in any additional solutions from front-end side

GraphQL service strongly depends on supporting frameworks both for front-end & back-end side, the variety of which isn't so large at the moment

Common pros and cons

REST

GraphQL

Better:

  • Easier cache handling

  • Less front-end tooling is required

  • Easier mime-types support

  • Lower learning curve

  • Larger community

  • Higher cloud support

Worse:

  • Lower flexibility

  • Worse performance

  • Harder versioning support

  • Harder introspection

  • Worse type checking

Better:

  • Higher flexibility

  • Better performance

  • Easier versioning support

  • Easier introspection

  • Better type checking

Worse:

  • Harder cache handling

  • More front-end tooling is required

  • Harder mime-types support

  • Higher learning curve

  • Smaller community

  • Lower cloud support

Detailed pros and cons

CRITERIA

REST

GraphQL

Flexibility

LOWER

Due to its design & philosophy REST API is not so easy to adapt for constantly changing client needs or for several clients at once.

That's why client side is responsible for creating additional logic for managing data relations (e.g.in order to get a comment client goes for all videos => gets video by id => gets its comments => gets comment by id). What turns out into overfetching & additional network roundtrips to retrieve all needed data.

HIGHER

GraphQL API is more flexible for different types of consumers due to its ability to serve exact data that each client needs. It reveals client side from additional logic on managing data relations & making additional network calls.

Performance

WORSE

Common performance concerns:

  • overfething for client side;

  • underfetching & additional roundtrips for client side;

BETTER

Common performance concerns:

  • too deep queries - can be managed by maximum query depth validator;

  • too complex queries - can be managed by query complexity validator;

  • N +1 problem - can be managed with batching technique;

Also query batching & deduplication techniques can be applied from client side to even more reduce the amount of network roundtrips.

Cache handling

EASIER

It's simpler to start with caching for REST API because:

  • http caching is out of the box & requires minimum server configuration;

  • tool-based caching (CDNs, in-memory & distributed caches) is widely spread, has wide variety of mature options;

  • doesn't need any additional effort from front-end side;

HARDER

It's harder to start with caching for GraphQL API because:

  • only tool-based caching (CDNs, in-memory & distributed caches) approach;

  • front-end effort might be needed;

Front-end tooling

LESS

Communication to REST service doesn't force any specific client architecture/framework

MORE

Communication to GraphQL service forces client to use specific architecture / frameworks (e.g. Relay, Apollo).

Versioning support

HARDER

REST service provides API level versioning. Each version should be handled separately, clients should switch all requests at once in order to migrate to new version.

EASIER

GraphQL service has field level versioning (unused fields are marked as deprecated). Clients can switch to new fields one by one, no need to do everything at once. Also a warning will be received in case of usage any deprecated field.

Introspection

HARDER

  • manually created API documentation which can be not relevant due to over time changes. Also it needs to be supported for all API versions;

  • tool based solutions (e.g. Swagger) that need manual set up;

EASIER

  • out of the box introspection is provided (GraphiQL);

  • advanced tools can be configured additionally (e.g. Insomnia);

Type checking

WORSE

Static type checking can be added during development. No data type checking in the run-time.

Exists mostly as a good will convention & doesn't guarantee the clients that the service is strictly following the types, which may cause bugs appearing at the very late stages of testing or in production.

BETTER

GraphQL heavily relies on strict data typing, there's no way to resolve types that are not declared in the schema otherwise the request will fail.

That guarantees the clients that all the types are strictly followed, type related bugs usually can be found during the development or at early stages of testing.

Supported mime-types

EASIER

Natural support for any type of data ,like multipart-form-data, application/octet-stream etc

HARDER

For not JSON data GraphQL needs additional configuration or workarounds

Learning curve

LOWER

Doesn't require any specific tool knowledge.

Optionally any frameworks, Typescript or any type checking tool.

HIGHER

Minimal knowledge includes: GraphQL query language, framework for building the API (e.g. Apollo), Typescript or any type checking tool.

Community

LARGER

Due to the fact that REST was the leading approach for building services for more than 10 years already, the community is very large, having accumulated a lot of recipes & best practices for most of the issues. Common problems & bottlenecks are well known. A lot of mature frameworks.

SMALLER

Due to novelty of the approach, the community isn't so large at the moment, new bottlenecks & problems can be found during development, which can or can't have any mature solutions & approaches. Best practices & commonly used recipes are in process of accumulation.

Cloud support

HIGHER

All cloud providers have hosted REST API service. The level of customization and additional features may differ, but it is always there.

LOWER

Only AWS has hosted GraphQL API solution (didn't find GCP or Azure having such service, but maybe I mis-googled it?) - AppSync, which also provides tooling for FE, mobile, and desktop clients.

All other cloud providers require deployment of a separate application or having GraphQL support built in BE application itself.

Last updated

Was this helpful?