An alternative to both REST & GraphQL, combining the benefits of each, based on https://tools.ietf.org/id/draft-snell-http-batch-00.html.
Batch multiple related requests into one HTTP request, which can be sent once & processed once on the server-side, but otherwise keep all the benefits of REST & HTTP. This is one single raw HTTP request:
POST /batch
Host: example.com
Content-Type: multipart/batch
--batch
Content-Type: application/http;version=1.1
Content-Id: author
Multipart-Failure: fail
GET /authors/5?fields=name
Accept: application/json
--batch
Content-Type: application/http;version=1.1
Content-Id: books
Parent-Content-Id: author
Multipart-Failure: ignore
GET /books?fields=title
Accept: application/json
Shown as HTTP/1.1 for readability, but there's no reason this couldn't work with HTTP 2 or 3. All the above is valid today, the only totally new headers are Multipart-Failure
(to describe what to if a part is not available) and Parent-Content-Id
(filters the books according to the related content). Otherwise it's all 100% standard REST & HTTP.
Equivalent to:
GET /authors/5?fields=name
Host: example.com
Accept: application/json
plus
GET /books?author=5&fields=title
Host: example.com
Accept: application/json
(or /author/5/books?fields=title
, if you prefer)
POST /graphql
Host: example.com
Accept: application/json
{
author(id: 5) {
name
books {
title
}
}
}
- One single batched request; sent in one go, can be processed server-side in one go, and returns a single consistent view of the data.
- CDNs & browser caches can cache each part of this, if they'd like.
- For root resources (author) that's trivial: understand the structure, cache exactly as normal
- For dependent resources (books) the cache can be aware of the relationship, and cache based on that. It needs to store the books request along with the base resource URL of the parent content. Could do this incrementally later, and cache just root data initially.
- Cache behaviour can be controlled with cache-control headers just like normal, content type negotiation per part works just like normal, etc etc.
- Unlike GraphQL, batches can be explicitly resilient to missing data (multipart-failure: ignore/fail in the headers)
- The response can be streamed as each part is available, rather than blocking for the whole batch, as GraphQL has to.
The response would also be a multipart response, with
In-Reply-To
refering to theContent-Id
of each part of the request, and each part of that response can be sent as soon as it's available on the server. - Separate headers mean you can do things like authenticate different parts of the same request independently, and/or use different content types for each, or whatever else you like.
- Data requests can be easily batched alongside resource requests (get a user and their profile photo), unlike GraphQL.
- No caches support this right now (but they totally could)
- None of your backend frameworks support this right now (but they totally could)
- None of your HTTP request libraries support this right now (but they totally could)