- Topics
- /
- /
- REST API alternatives
Beyond REST: The best alternatives for client-server communication
REST (Representational State Transfer) is one of the most impactful technologies of the past 20 years - enabling everything from smart light bulbs to your mobile banking app. And no wonder. Using the web’s HTTP-based patterns and technologies to build APIs provides a great shortcut because it allows for the reuse of the same knowledge, tooling, and infrastructure. That makes it easier to get projects to market faster.
But REST isn’t the only way to build an API. And for some use cases, it’s the wrong choice altogether. That’s because REST’s web heritage makes it a good fit for CRUD (Create, Read, Update, Delete) applications but not so much for others. For example, what if you need a persistent, stateful connection in a chat app? Or maybe you’re building a social media app that relies on complex, interconnected data.
In this article, we’ll look at the pros, cons, and ideal use cases of four REST alternatives: GraphQL, gRPC, MQTT, and WebSocket. But first, let’s make sure we understand REST itself.
What is REST?
REST is so much a part of modern development that it’s easy to take it for granted, so let’s recap what REST is and how it works, as well as its strengths and weaknesses.
First up, REST isn’t a protocol; it’s an architectural style. As such, it leaves a lot of design decisions to you. The upside is that you can build exactly what you need, with REST principles. But it also means REST APIs can differ significantly, making them harder to learn and maintain. That’s in contrast to the alternatives we look at below, which each define a strict way to implement the protocol.
So, what does this architectural style specify? REST APIs all share the following characteristics:
They are resource-based: Each end-point corresponds to a specific resource, such as a user, a product, or a transaction. For example, calling /products might list all the products in an online store. Calling /products/1234 would return a specific product.
They use HTTP verbs: REST APIs implement the CRUD pattern using five HTTP methods:
GET: Reads data from a resource.
POST: Creates a new resource.
PUT: Updates an existing resource by replacing it.
PATCH: Updates an existing resource by modifying parts of it.
DELETE.
They are stateless: Each REST request is self-contained. That’s great for scalability but nearly all web applications depend on external state storage to keep track of state that is too large or too complex to fit into request headers.
They use workarounds to track state: Just as with web browsing, cookies and tokens provide a way to identify individual clients and authenticate them with a specific session.
Responses are cacheable: Both clients and server-side components can cache responses, in part because they are stateless.
Responses are synchronous: Following HTTP’s request-response pattern makes it harder to build REST APIs that rely on long-running connections.
The server-side can be layered: So long as the endpoints stay the same, REST API clients have no visibility of what they’re interacting with. That means the backend architecture can involve caches, load balancers, edge nodes, and more.
As end-users demand more of the services we build, it becomes more apparent that REST is just one approach available to us.
Why you might need an alternative to REST
As convenient as REST is, some of the things that make it easy to work with can also lead to challenges, such as:
Increased complexity: The downside of REST's flexibility is that it requires you to make decisions and implement functionality that comes for free in more rigidly defined protocols.
Over-fetching and under-fetching: REST query is simple by design. That puts the onus on you to design an API that anticipates all future requests. In practice, clients end up fetching more data they need, and processing it locally, or making multiple requests. Either way, it adds latency and wastes resources.
Discoverability is poor: HATEOAS helps with discoverability but it’s like navigating a maze without a map. Without an explicit data schema, it’s harder to test, develop against, and maintain REST APIs
Hard to manage state: Statelessness helps scaling but makes it harder to manage stateful interactions, such as realtime data streaming or collaborative editing.
Versioning is a hack: REST doesn’t have an opinion on how to version APIs, which complicates backward compatibility and adds another learning step each time a developer comes to learn a REST API.
This isn’t an exhaustive list, but it does illustrate some of the reasons why you might want to consider an alternative approach.
Evaluating REST alternatives
It’s clear that there are gaps in what REST has to offer. But what should we consider when looking at other options?
Performance: How well each alternative handles data transfer and processing.
Scalability: Does introducing additional functionality necessarily make a protocol or approach harder to scale than REST?
Developer experience: Are the learning curve and complexity of both implementation and maintenance worth any other benefits offered over REST?
Use case suitability: What use cases does that approach serve best? And are there scenarios where it’s not appropriate?
Let’s evaluate these criteria, as well as other pros and cons, for the following REST alternatives:
GraphQL
gRPC
WebSocket
MQTT
GraphQL
Created by Facebook in 2012, and open-sourced in 2015, GraphQL sets out to solve key limitations in REST with four goals:
Support for complex data: REST APIs tend to work best with hierarchical data formats that can be delivered in a single response, such as JSON and XML. HATEOAS links can enable the client to navigate linked data, using additional requests. GraphQL, though, is designed to deal with interconnected data, making it perhaps its greatest strength.
Explicit schema: REST’s implied schema can make it easier to get started with an API and allows for spontaneous changes to an API’s design. However, GraphQL’s declared schema and strict type system allow you to understand the API’s scope up front and make useful tooling, such as automatic documentation generators and query generators, possible.
Efficient data fetching: GraphQL’s declarative language lets you specify the data you want without having to think about how to retrieve it. That increases the chance you’ll retrieve precisely the data you’ll need and reduces data transfer.
Seamless API evolution: REST’s reliance on URI endpoints makes REST APIs more brittle. Changes to how resources are represented can break older clients. While REST API versioning offers a workaround, GraphQL’s explicit schema allows clients to navigate schema and query changes.
It’s useful to think of GraphQL as a complement to REST, rather than as a replacement for it. For instance, in an online store product categories and specific product details usually remain static. That makes them easy to cache and ideal for calling with a simple GET directed to the right endpoint. A custom product query, with search terms and filters, would be harder to achieve through REST but it would be ideally suited to GraphQL. To perform that search with REST might take several queries, or require over fetching a huge chunk of data and filtering it on the client. GraphQL can do it in one request.
With that in mind, what are the advantages, disadvantages, and use cases of GraphQL?
GraphQL advantages
Query precision: GraphQL returns the data you need in just one query, reducing the risk of over and under-fetching.
Single end-point: Rather than needing to know the structure of multiple end-points, and call several of them to pull off a complex query, GraphQL lets you focus on the data you want to retrieve.
Reduced network traffic: Relatedly, GraphQL requires fewer individual HTTP calls, each of which brings additional overhead.
Less chance of errors: GraphQL’s strong typing and explicit schema minimize the likelihood of errors by enforcing a clear contract for data types and structures.
GraphQL disadvantages
Queries can become complicated: The flipside of asking the query language to do more work is that queries themselves can become quite involved. Just like SQL, the more complex a query is the higher the chances are that it will perform poorly. Complex queries are also harder to read and maintain.
Harder to cache: In REST, standard HTTP caching is more straightforward because resources live behind unique URLs. This predictability makes caching easier. However, each GraphQL query could be different from the last, making it harder to cache.
No native support for binary data: REST doesn’t specify the format of requests and responses. That gives you scope to use binary formats such as Protocol Buffers. Standard GraphQL requests and responses must be in JSON, though.
GraphQL use cases
Low bandwidth scenarios: GraphQL’s query language lets you fetch precisely the data you need with a single query. That requires more up-front knowledge of the API than REST but it also reduces bandwidth lost on multiple queries, as well as over-fetching.
Applications with complex data structures: A single GraphQL query can retrieve data from multiple resources in a system. For example, in an e-commerce application, one GraphQL query could retrieve a customer’s order history, along with the product and pricing information for each order, whereas that might require three or more queries in the case of REST. On top of the additional requests, REST would require potentially complex client-side processing to bring together the data from those requests.
Retrieving data from multiple sources: The data sources for an application, such as the e-commerce one above, could be in completely separate systems. GraphQL’s schema stitching allows API builders to aggregate multiple data sources into a single schema. This simplifies client code and allows you as a developer to think about the data you want to retrieve rather than the details of how it is stored on the server-side.
Subscriptions: GraphQL offers two ways to subscribe to realtime data sources:
Live queries: When data changes, the server reruns the entire query and pushes the result to the client. This method is ideal for sporadic updates, such as changing the readings on a live dashboard.
Event-driven subscriptions: For long-running subscriptions, GraphQL can open a persistent connection using a variety of protocols, such as WebSocket. Rather than rerunning a query each time, GraphQL sends only new data when an event generates it. For example, blow-by-blow updates from a sports match streamed to a fan app.
gRPC is an open-source protocol and framework, originating at Google, designed for communication between microservices in distributed systems. Based on the idea of remote procedure calls (RPC), gRPC offers:
HTTP/2 transport: HTTP/2 builds on HTTP/1.1 by adding support for binary headers, compression, multiplexing, and prioritization of requests. gRPC puts this to use with features such as bidirectional streaming, smaller message payloads due to binary serialization, and efficient connection management, which enhances performance and reduces latency.
Binary responses: gRPC sends data using Protocol Buffers, which is a strongly typed binary data format. Being binary reduces overhead both during transport and when parsing on the client or server side, as well as reducing the chance of data transcription errors. Strong typing improves error validation.
Different types of streaming: gRPC offers four types of connection:
Unary: The connection opens for a single request/response cycle, like REST.
Server streaming: The client makes a request and the server responds with a stream that remains open for as long as is necessary.
Client streaming: Similarly, the client sends a stream of data to the server and closes the session once the server acknowledges receipt.
Bidirectional streaming: gRPC establishes two independent persistent connections, one for the client to send data and the other for the server.
Message ordering: In a bidirectional stream, gRPC delivers messages in the order they were sent.
Native language query: Unlike GraphQL - which has its own query language, or REST - where we request resources from URIs, gRPC uses Protocol Buffers’ language-agnostic Interface Definition Language (IDL). That lets the client and the server generate classes and methods (or the equivalent in the language you’re using), so you can access the API’s resources as though they’re local.
Now that we’ve looked at the key characteristics of gRPC, let’s move on to what it does well, where it’s not so strong, and the situations it suits particularly well.
gRPC advantages
Strong contract: By defining the API upfront with Protocol Buffers' Interface Definition Language, gRPC removes ambiguities about the API's capabilities, while providing type safety and easier API evolution, as changes are explicitly managed through the Protobuf schema.
Low latency: HTTP/2 gives gRPC a whole raft of latency advantages, including binary headers to reduce overhead. Protocol Buffers then remove the cost of converting text-based JSON or XML.
Support persistent connections: REST’s stateless model has its place but gRPC’s support for persistent connections enables realtime streaming, as well as offering more flexibility over the type of connection, as we’ve seen with unary, bidirectional, and other types.
gRPC disadvantages
No native browser support: Right now, no browser exposes HTTP/2 frames to the JavaScript environment. That makes it impossible for gRPC to run natively in browsers. Instead, there is a JavaScript gRPC client (grpc-web) that supports only unary and server-side connections. But even then the support is incomplete as only the unary mode supports protobufs, while server-side connections must serialize to JSON. Without HTTP/2 underneath, grpc-web misses out on the multiplexing and lower latencies that protocol enables. Perhaps the biggest downside is that grpc-web requires a proxy server between the browser and the GRPC server.
Harder to learn: gRPC isn’t built on web principles, and so you might see a productivity dip as you get up to speed.
Less compatibility: gRPC works at its best where HTTP/2 is available, so you might need to ensure that all of the infrastructure in your system, such as firewalls, proxies, and load balancers, also support HTTP/2.
gRPC use cases
While we might tend to think of REST in terms of public APIs, gRPC’s main use is for communication between microservices. And that’s reflected in the lack of native browser support.
Although REST is often associated with public APIs, it's also widely adopted in microservices architectures, which is gRPC’s primary niche. That’s most likely thanks to GRPC’s developer experience, which abstracts away the network mechanics and makes the API’s functionality available as local objects and methods. That combined with low latency, both on the transport side and in terms of the speed of serializing/ deserializing protocol buffers data, also suits the protocol well to microservices where, in effect, an API needs to deliver the same responsiveness as local functionality.
WebSocket
Up until this point, we’ve looked at architectural patterns and frameworks that provide an opinionated end-to-end approach to building APIs. But WebSocket is different. It’s a protocol and an API designed for bidirectional, persistent, and low-latency connections that work for realtime scenarios rather than request-response cycles.
So, why are we including WebSocket in this comparison? Modern mobile and web applications increasingly center on realtime experiences such as live chat, dynamic dashboard updates, and collaborative environments like Google Docs and Figma. HTTP long polling enables REST APIs to attempt to make things realtime - but it’s a workaround. WebSocket maintains an open connection, meaning updates can go in either direction as soon as an event occurs.
By looking a little closer, we can see where WebSockets does well, where it falls down, and when to use it.
WebSocket advantages
Realtime delivery: WebSocket’s design is built from the ground up for realtime data, delivery and significantly reduces overhead accordingly. The persistent, two-way connection removes the need for repeated new connections, as would be the case if attempting to build with REST on top of HTTP. The continuous data flow also removes the delay from request-response cycles.
Two-way communication: Enabling both client and server to send and receive messages at the same time reduces the overhead of managing two separate connections.
Widely available: All currently supported web browsers support WebSocket natively, while web frameworks and languages each have WebSocket libraries or built-in support.
WebSocket disadvantages
Stateful connections are harder to scale: WebSocket connections are stateful, meaning that horizontally scaling a cluster of servers behind a load balancer takes more planning and code to ensure connections stick to the same server.
No automatic reconnections: If a WebSocket connection fails, there ’s nothing in the API or protocol to enable automatic reconnection. You’ll need to code that manually.
Not suited to building an API: Remember that HTTP, and by extension REST, is stateless, while WebSocket relies on a persistent, two-way connection. If what you really need is an API that delivers discrete functionality on a response-request model, then WebSocket isn’t the right choice. For one thing, managing that ongoing, two-way connection requires more memory and processing than responding to ad-hoc REST/HTTP requests. WebSockets are also harder but not impossible to scale horizontally, due to the stateful nature of ongoing connections. The same goes for caching responses and storing them closer to users in edge locations. While a realtime PaaS, such as Ably, helps mitigate those limitations, it’s better to use the right tool for the right job.
WebSocket use cases
Live chat: The persistent, two-way connection that WebSocket maintains makes it ideal for live chat applications. Messages between chat users are sent with minimal latency to a central server for distribution to their intended recipient clients.
Collaborative workspaces: Bringing distributed participants together to collaborate on editing a document, updating tasks in a project management tool, or designing together in a shared whiteboard, works only if the tool can distribute updates in realtime. For instance, small messages such as cursor movements or text changes are sent from one client to the server and then synchronized across all other clients, ensuring everyone's view is consistently up to date.
Notifications and alerts: Pushing in-app notifications to users, such as a goal announcement in a soccer app or snow warning in a weather app, would require inefficient workarounds, such as manual polling, to achieve with a REST API.
MQTT (Message Queuing Telemetry Transport) is another persistent communication protocol, making it quite different from REST. It also serves a different niche when compared to WebSocket.
Designed for IoT: MQTT is intended for resource-constrained environments, such as IoT devices with poor network connectivity. That’s reflected in reduced overhead and tunable data integrity guarantees.
Publish-subscribe: Clients publish messages to channels that are then distributed by a central broker to other subscribers.
Clients can specify what happens when they disconnect: As part of tolerating unpredictable environments, MQTT clients can specify a message that will be published to the broker in the event of their unplanned disconnection. This is called their last will and testament.
So, what are MQTT’s plus points, its negatives, and its most suitable use cases?
MQTT advantages
Lightweight: MQTT sends data in a binary format, reducing the overhead of JSON and similar text-based formats. Messages are also compressed, while a fixed, minimal header size reduces overhead. This is one reason that Facebook chose MQTT for their Messenger product back in 2011, a time when battery life and processing power were much more limited in mobile devices.
Scalable: The publish-subscribe model makes it relatively easy to scale MQTT.
Message guarantees: MQTT allows you to choose the trade-off between delivery guarantee and overhead that best suits your application, with options for at least once, at most once, and exactly once.
MQTT disadvantages
Limited functionality: The protocol’s focus on streaming messages to and from IoT devices means that MQTT lacks some of the features you might find with a fully-featured API protocol.
No way to discover services: Unlike REST or GraphQL, for example, MQTT offers no way to discover what services are available. Instead, you must know the address of the MQTT broker up-front.
Security and auth options: MQTT relies on TLS to encrypt communications and also uses TLS certificates as a form of client authentication. That’s fine in a situation where those clients are centrally controlled IoT devices but as a form of end user authentication, it would introduce too much friction. MQTT does offer username and password-based authentication, which is subject to brute forcing and similar attacks.
MQTT use cases
Sensor data: MQTT’s lightweight design makes it ideal for streaming updates from IoT sensors, such as thermostats, smart meters, and asset tracking systems, back to central management tools reliably.
Device control: Sending instructions to IoT devices, such as an actuator that opens a greenhouse window.
Edge computing: Managing and monitoring devices at the edge of networks, such as surveillance cameras or gateways between networks.
Matching REST and its alternatives to use cases
There’s a lot to consider when comparing protocols, frameworks, and architectural patterns. But what matters most is whether a particular approach can meet the needs of your use case.
Use case | REST | GraphQL | gRPC-web | WebSocket | MQTT |
CRUD | x | x | x | ||
Complex data query | x | x | |||
Binary data transfer | x | x | x | ||
Realtime experiences | x | x | |||
IoT | x | ||||
Data broadcast | x | x | |||
Connecting microservices | x | x | x |
Putting REST and its alternatives into perspective
Without REST, the web would be harder to develop for - and probably, less rich as a result. However, as we’ve seen here, what makes REST great for creating CRUD APIs is also what limits it in other scenarios.
The reality of modern web and mobile development is that REST is just one of the broad approaches we can take. And the increasing prevalence of realtime experiences means that protocols such as WebSocket are taking their place alongside older alternatives. WebSocket, in particular, offers an entirely different solution to a problem that HTTP-based workarounds, including long polling, have tried to solve. And that means WebSocket lives alongside REST as a complement rather than a replacement. That might not be so true for GraphQL.
Managing the infrastructure for those realtime experiences, though, is substantially more work than standing up a typical REST backend. That’s why we built our realtime platform as a service (PaaS) here at Ably.
Using Ably, you can reduce your app’s time to market, save engineering budget, and deliver richer functionality. Here are some of the reasons you should consider our PaaS:
Our global edge network delivers unrivaled redundancy at regional and global levels, with a five nines uptime SLA.
<65 ms median latency.
Messages are guaranteed to be delivered in order and exactly once delivery, even in unstable network conditions.
Enormous scalability means you can send billions of messages to millions of channels and chat users.
Check it out for yourself by creating a free account.
Recommended Articles
gRPC vs. WebSocket: Key differences and which to use
Discover the different features, performance characteristics, and use cases for gRPC and WebSockets to help understand which technology suits your needs best.
MQTT vs. WebSocket - Key differences and when to use them together
Discover the different features, performance characteristics, and use cases for MQTT and WebSocket, and when (if ever) they should be used together.
The challenge of scaling WebSockets [with video]
Scaling WebSockets in production can be challenging in terms of load balancing, fallbacks, and connection management. Here's how to tackle it and scale WebSockets efficiently.