2 Comparing gRPC with REST and GraphQL
In the modern era of distributed systems and microservices development, the need for inter-service communication has become increasingly crucial. Three fairly popular approaches are REST, GraphQL, and gRPC. Each has its own philosophy, strengths, and weaknesses. In this article, I’ll break down all three from a technical standpoint, comparing their performance, use-case scenarios, and providing simple code examples so we can choose the one that best fits our needs.
A Quick Look at REST, GraphQL, & gRPC
REST (Representational State Transfer) has been a mainstay of API development for many years. The concepts of resources, HTTP verbs, and statelessness make REST very easy to understand and implement.
GraphQL is an alternative query language from Facebook that gives clients a high degree of flexibility to select exactly the data they need.
gRPC is a Remote Procedure Call (RPC) communication framework built by Google that uses Protocol Buffers as its serialization format. gRPC supports streaming and delivers far more efficient performance thanks to its binary protocol.
Comparison Table: REST vs GraphQL vs gRPC
| Feature | REST | GraphQL | gRPC |
|---|---|---|---|
| Protocol | HTTP/1.1 | HTTP/1.1/2 | HTTP/2 |
| Data Format | JSON/XML | JSON | Protocol Buffers (binary) |
| Schema | Not required (OpenAPI optional) | Required, via type system | Required, via Protobuf (.proto) |
| Performance | Decent, text-based | Similar to REST | Very fast, binary, multiplexed |
| Client-Server | Client-driven | Client-driven | Contract-first, server-defined |
| Realtime/Streaming | Polling/optional WebSocket | Realtime subscription | Native streaming (bidirectional) |
| Dev tools | Many, mature | Many, still young | Multi-language generators, active |
| Interop | Easy, Web standard | Easy, Web standard | Many languages, native protocol |
| Versioning | Via URL/headers | Introspective, non-breaking | Through .proto evolution |
Flow Diagram: The Request-Response Model
Let’s visualize the simple flow of data between client and service for each technology:
flowchart LR
subgraph REST
A[Client] -->|HTTP GET/POST| B[REST API]
B -->|JSON Response| A
end
subgraph GraphQL
C[Client] -->|Query / Mutation| D[GraphQL Server]
D -->|JSON Response| C
end
subgraph gRPC
E[Client Stub] -->|Proto
Request Message | F[gRPC Server]
F -->|Proto
Response Message | E
end
When Should You Use REST, GraphQL, or gRPC?
REST is a good fit for:
- Public web applications/third-party APIs
- Extensive documentation and tooling
- Rapid prototyping
GraphQL is a good fit for:
- Mobile/web clients with dynamic data needs or minimal payloads
- Aggregating various data sources (API gateway)
- Complex relationships between resources
gRPC is a good fit for:
- Internal communication between microservices
- High-performance requirements (low latency, high throughput)
- Real-time systems and data streaming
Code Examples: REST vs GraphQL vs gRPC
1. REST (Express.js)
1const express = require('express');
2const app = express();
3
4app.get('/books/:id', (req, res) => {
5 // Simulate getting data
6 res.json({ id: req.params.id, title: "Clean Code", author: "Robert C. Martin" });
7});
8
9app.listen(3000, () => console.log('REST API on port 3000'));2. GraphQL (Apollo Server)
1const { ApolloServer, gql } = require('apollo-server');
2
3// Type definitions
4const typeDefs = gql`
5 type Book { id: ID!, title: String!, author: String! }
6 type Query { book(id: ID!): Book }
7`;
8
9// Resolvers
10const resolvers = {
11 Query: {
12 book: (_, { id }) => ({ id, title: "Clean Code", author: "Robert C. Martin" })
13 }
14};
15
16// Server
17const server = new ApolloServer({ typeDefs, resolvers });
18server.listen().then(({ url }) => console.log(`GraphQL ready at ${url}`));3. gRPC (Node.js)
a. Protobuf Definition (book.proto):
1syntax = "proto3";
2
3service BookService {
4 rpc GetBook(GetBookRequest) returns (Book);
5}
6
7message GetBookRequest { string id = 1; }
8message Book { string id = 1; string title = 2; string author = 3; }b. Server Implementation:
1const grpc = require('@grpc/grpc-js');
2const protoLoader = require('@grpc/proto-loader');
3
4const packageDefinition = protoLoader.loadSync('book.proto');
5const bookProto = grpc.loadPackageDefinition(packageDefinition);
6
7function getBook(call, callback) {
8 callback(null, { id: call.request.id, title: "Clean Code", author: "Robert C. Martin" });
9}
10
11const server = new grpc.Server();
12server.addService(bookProto.BookService.service, { GetBook: getBook });
13server.bindAsync('127.0.0.1:50051', grpc.ServerCredentials.createInsecure(), () => server.start());A Simple Benchmark: REST vs gRPC
Here is a simulated speed comparison of the core characteristics of REST and gRPC (excluding GraphQL, since the performance focus here is REST vs gRPC):
| Request Count | REST (ms) | gRPC (ms) | Difference |
|---|---|---|---|
| 500 | 850 | 105 | 745 |
| 1000 | 1580 | 182 | 1398 |
| 10,000 | 13300 | 1400 | 11900 |
Complex Data Fetching: Overfetching and Underfetching
- REST: The response stays the same even if the client only needs a single field.
- GraphQL: The client can specifically request whichever fields it wants.
- gRPC: Similar to REST (one RPC returns one fixed response), but more flexible because you can design more granular services.
Example of a GraphQL query that only needs title and doesn’t need author:
1query {
2 book(id: "1") { title }
3}REST and gRPC must return all the values defined by the endpoint/service, or you have to customize them.
Development and Tools
- REST: OpenAPI/Swagger, Postman, Insomnia
- GraphQL: GraphQL Playground, Altair, Apollo Studio
- gRPC: Evans, grpcurl, Postman (limited)
API Evolution & Versioning
- REST: /api/v1/books, /api/v2/books
- GraphQL: Generally non-breaking, introspective schema
- gRPC: Supports evolution (proto field numbers must not be changed) and optional fields
Conclusion
Technically, REST offers a simplicity that many developers love, especially for public APIs. GraphQL solves the overfetching and underfetching problem with flexible, client-side queries. On the other hand, gRPC is the modern choice for machine-to-machine communication in microservices environments that demand high performance and efficiency.
Recommendation:
- For public APIs or integration with many external clients: REST or GraphQL.
- For internal APIs where performance and speed are the priority: gRPC.
Every path has its own characteristics. Choose based on your needs, your team, and your ecosystem!
References: