TL;DR
Use REST for public APIs and straightforward CRUD operations. Choose GraphQL when clients need flexible data fetching and you want to reduce over-fetching. Use gRPC for high-performance communication between internal services. Modern PetstoreAPI implements all three protocols, so you can compare them and choose the right option for each use case.
Introduction
When you build an API, should you use REST, GraphQL, or gRPC? Each protocol solves a different problem, so the best choice depends on your clients, performance requirements, and operational constraints—not on which protocol is universally “better.”
REST is widely supported and simple to operate. GraphQL lets clients control the shape of their responses. gRPC provides efficient communication and native streaming for internal services.
Most APIs use one protocol exclusively. Modern PetstoreAPI takes a different approach: it implements the same pet store API with REST, GraphQL, and gRPC. This makes it possible to compare equivalent operations across all three protocols.
If you’re building or testing APIs, Apidog supports REST, GraphQL, and gRPC in one tool. You can test each protocol, compare responses, and verify consistency across implementations.
In this guide, you’ll learn:
- How each protocol works
- The strengths and weaknesses of REST, GraphQL, and gRPC
- Equivalent PetstoreAPI operations in all three protocols
- How to test a multi-protocol API
- How to choose a protocol for a new service
REST: The Universal Standard
REST, or Representational State Transfer, is the most common approach for HTTP APIs.
How REST Works
REST models data as resources. URLs identify resources, while HTTP methods describe the requested operation:
| Operation | Method and path |
|---|---|
| List pets | GET /pets |
| Create a pet | POST /pets |
| Get a pet | GET /pets/{id} |
| Update a pet | PUT /pets/{id} |
| Delete a pet | DELETE /pets/{id} |
For example:
GET https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24
A successful response might look like this:
{
"id": "019b4132-70aa-764f-b315-e2803d882a24",
"name": "Fluffy",
"species": "CAT",
"status": "AVAILABLE",
"price": 299.99
}
REST Strengths
1. Universal compatibility
Every major programming language has HTTP libraries. Browsers, command-line tools, API clients, and proxies all work with REST.
2. Simple mental model
URLs represent resources, and HTTP methods represent actions. The resulting API is easy to understand and document.
3. Built-in caching
HTTP caching works naturally with REST. Browsers, CDNs, and proxies can cache GET responses when the appropriate cache headers are configured.
4. Stateless requests
Each request contains the information needed to process it. The server does not need to maintain conversational state between requests.
5. Mature tooling
REST has a broad ecosystem based on OpenAPI, Swagger UI, API gateways, testing tools, and monitoring platforms.
REST Weaknesses
1. Over-fetching
A REST endpoint often returns a fixed response shape. If a client only needs a pet’s name, it may still receive every available field:
{
"id": "019b4132-70aa-764f-b315-e2803d882a24",
"name": "Fluffy",
"species": "CAT",
"status": "AVAILABLE",
"price": 299.99,
"description": "...",
"images": [],
"vaccinations": []
}
2. Under-fetching and the N+1 problem
Fetching related data can require multiple requests:
GET /pets/123
GET /pets/123/orders
GET /orders/456/items
Each additional request adds latency and increases client-side coordination.
3. Versioning complexity
Breaking changes commonly require a new URL or versioning strategy, such as /v1 and /v2.
4. No native real-time updates
REST follows a request-response model. Real-time behavior generally requires polling, server-sent events, or WebSockets.
When to Use REST
REST is a good default for:
- Public APIs that need maximum compatibility
- Simple CRUD operations
- APIs where HTTP caching is important
- Services that need broad tooling support
- Mobile apps with predictable data requirements
Modern PetstoreAPI REST implementation
GraphQL: Flexible Data Fetching
GraphQL allows clients to describe the exact data they need in a query.
How GraphQL Works
A GraphQL API typically exposes a single endpoint, such as /graphql, and uses a query language to select fields and relationships:
query {
pet(id: "019b4132-70aa-764f-b315-e2803d882a24") {
name
species
orders {
id
total
items {
product
quantity
}
}
}
}
The response follows the shape of the query:
{
"data": {
"pet": {
"name": "Fluffy",
"species": "CAT",
"orders": [
{
"id": "order-123",
"total": 49.99,
"items": [
{
"product": "Cat food",
"quantity": 2
}
]
}
]
}
}
}
GraphQL Strengths
1. Reduced over-fetching
Clients request only the fields they need:
query {
pet(id: "019b4132-70aa-764f-b315-e2803d882a24") {
name
}
}
This can reduce payload size, especially for mobile clients or clients operating over slower networks.
2. Reduced under-fetching
Clients can request related resources in the same operation:
query {
pet(id: "019b4132-70aa-764f-b315-e2803d882a24") {
name
orders {
items {
product
}
}
}
}
The client does not need to coordinate several REST requests for this data.
3. Strong typing
A GraphQL schema defines available types, fields, arguments, queries, and mutations. Client tools can use the schema for validation and autocomplete.
4. Introspection
Clients and tools can inspect the schema:
query {
__schema {
types {
name
fields {
name
type
}
}
}
}
5. A single endpoint
All operations use one endpoint, usually /graphql. This can simplify client configuration and API discovery.
GraphQL Weaknesses
1. Greater implementation complexity
GraphQL introduces schemas, queries, mutations, subscriptions, and resolvers. Teams need to understand how these pieces work together.
2. More difficult caching
Standard HTTP caching is less straightforward when many operations use the same endpoint. Applications often need custom caching strategies or client-side normalized caches.
3. Risk of expensive queries
Clients can request deeply nested relationships:
query {
pets {
orders {
items {
product {
reviews {
author {
pets {
name
}
}
}
}
}
}
}
}
Production GraphQL services typically need query depth limits, complexity analysis, pagination, and resolver safeguards.
4. File uploads require additional handling
GraphQL was not designed specifically for file uploads. Implementations generally use an upload specification or a separate object-storage workflow.
5. Monitoring requires extra context
Because many operations use /graphql, URL-based monitoring is not enough. Logs and metrics should include the operation name and other query metadata.
When to Use GraphQL
GraphQL is a good fit for:
- Mobile applications that need to reduce bandwidth
- Clients with complex or varying data requirements
- Products where clients need control over response fields
- Internal APIs with a known set of consumers
- APIs where schema evolution is preferred over URL versioning
Modern PetstoreAPI GraphQL implementation
gRPC: High-Performance RPC
gRPC uses Protocol Buffers to define services and exchange compact binary messages.
How gRPC Works
First, define the service contract in a .proto file:
service PetService {
rpc GetPet(GetPetRequest) returns (Pet);
rpc ListPets(ListPetsRequest) returns (ListPetsResponse);
rpc CreatePet(CreatePetRequest) returns (Pet);
}
message Pet {
string id = 1;
string name = 2;
string species = 3;
PetStatus status = 4;
}
A code-generation tool creates client and server types from this definition. A Go client can then call the service like this:
client := pb.NewPetServiceClient(conn)
pet, err := client.GetPet(ctx, &pb.GetPetRequest{
Id: "019b4132-70aa-764f-b315-e2803d882a24",
})
gRPC Strengths
1. Performance
Protocol Buffers generally produce smaller payloads and faster serialization than JSON. Depending on the message shape and implementation, they can provide:
- 3–10x smaller payloads
- 20–100x faster serialization
Actual results depend on the data, network, and runtime, so benchmark representative workloads before making a decision.
2. Native streaming
gRPC supports server streaming, client streaming, and bidirectional streaming:
rpc WatchPets(WatchPetsRequest) returns (stream Pet);
3. Strong typing
Protocol Buffer definitions enforce message types and enable compile-time validation in generated clients and servers.
4. Code generation
A single .proto definition can generate client and server code for more than 10 languages.
5. HTTP/2 transport
gRPC uses HTTP/2 features such as multiplexing and header compression.
gRPC Weaknesses
1. Limited browser support
Browsers do not directly support all HTTP/2 features required for standard gRPC bidirectional communication. Browser clients generally need grpc-web, which adds another layer.
2. Binary messages are not human-readable
You cannot inspect a normal gRPC response with curl in the same way you can inspect JSON.
3. Debugging requires specialized tools
Binary payloads and generated code can make local inspection more difficult than debugging a JSON API.
4. Smaller tooling ecosystem
gRPC has fewer general-purpose tools than REST and does not have a direct equivalent to the REST/Swagger UI workflow.
5. Steeper learning curve
Teams need to learn Protocol Buffers, code generation, service definitions, and gRPC-specific concepts.
When to Use gRPC
gRPC is a strong choice for:
- Communication between microservices
- High-throughput or low-latency workloads
- Real-time streaming
- Internal APIs
- Polyglot environments with services written in multiple languages
Modern PetstoreAPI gRPC implementation
Side-by-Side Comparison
| Feature | REST | GraphQL | gRPC |
|---|---|---|---|
| Protocol | HTTP/1.1 or HTTP/2 | HTTP/1.1 or HTTP/2 | HTTP/2 |
| Data format | JSON, usually | JSON | Protocol Buffers, binary |
| Endpoints | Multiple, such as /pets and /orders
|
Usually one, such as /graphql
|
Service methods |
| Over-fetching | Common | Rare | N/A; messages are explicitly defined |
| Under-fetching | Common for related resources | Rare | N/A |
| Caching | Excellent with HTTP caching | More difficult | More difficult |
| Browser support | Excellent | Excellent | Limited; usually needs grpc-web
|
| Tooling | Excellent | Good | Fair |
| Learning curve | Easy | Medium | Hard |
| Performance | Good | Good | Excellent |
| Streaming | Requires WebSockets or another mechanism | Subscriptions | Native |
| Versioning | URL or header versioning | Schema evolution | Protocol Buffer evolution |
| Best for | Public APIs and CRUD | Flexible clients | Internal services and microservices |
How Modern PetstoreAPI Implements All Three
Modern PetstoreAPI exposes the same pet store operations through REST, GraphQL, and gRPC. This makes it possible to compare protocol behavior without changing the underlying business operation.
Get the Same Pet Three Ways
REST
GET https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24
GraphQL
query {
pet(id: "019b4132-70aa-764f-b315-e2803d882a24") {
id
name
species
}
}
gRPC
pet, err := client.GetPet(ctx, &pb.GetPetRequest{
Id: "019b4132-70aa-764f-b315-e2803d882a24",
})
All three operations return the same pet data while exposing different client and transport models.
Why Implement All Three?
1. Learn by comparison
You can see how the same operation is represented as an HTTP resource, a GraphQL query, and an RPC method.
2. Match the protocol to the client
A common approach is:
- REST for public endpoints
- GraphQL for mobile applications and flexible clients
- gRPC for internal microservices
3. Support gradual adoption
A team can start with REST and add GraphQL or gRPC later without replacing the underlying business logic.
4. Provide a reference implementation
Modern PetstoreAPI demonstrates patterns for implementing the same API concepts across all three protocols.
Check the protocol comparison guide for more detailed examples.
Testing Multi-Protocol APIs with Apidog
Apidog supports REST, GraphQL, and gRPC in one tool. A practical cross-protocol test workflow is:
- Import the contract for each protocol.
- Create an equivalent “get pet” request.
- Run the requests with the same pet ID.
- Validate required fields and values.
- Compare the responses across protocols.
Test a REST Endpoint
After importing an OpenAPI specification, add response assertions:
pm.test("Status is 200", () => {
pm.response.to.have.status(200);
});
pm.test("Pet has required fields", () => {
const pet = pm.response.json();
pm.expect(pet).to.have.property("id");
pm.expect(pet).to.have.property("name");
});
Test a GraphQL Query
Use variables rather than hard-coding IDs into every query:
query GetPet($id: ID!) {
pet(id: $id) {
id
name
species
}
}
Apidog validates the query against the GraphQL schema.
Test a gRPC Method
Import the .proto files, then select the service and method:
service: PetService
method: GetPet
request: {
"id": "019b4132-70aa-764f-b315-e2803d882a24"
}
Apidog generates requests from the Protocol Buffer definitions.
Add Cross-Protocol Checks
For each protocol, verify the same canonical fields:
- The request succeeds
- The returned ID matches the requested ID
- The pet name is the same
- The species is the same
- The status and price follow the same business rules
This catches inconsistencies between protocol adapters and the shared business logic.
Choosing the Right Protocol
Use this decision process when starting a new API:
-
Is this a public API?
- Yes: Start with REST for maximum compatibility.
- No: Continue evaluating the client and service requirements.
-
Do you need real-time streaming?
- Yes: Use gRPC or WebSockets, depending on the clients.
- No: Continue.
-
Do clients need flexible data fetching?
- Yes: Consider GraphQL.
- No: Continue.
-
Is performance critical for internal service communication?
- Yes: Consider gRPC.
- No: REST is usually the simplest option.
Real-World Examples
- Stripe: REST for a public API with predictable operations
- GitHub: REST and GraphQL for both standard and complex queries
- Google Cloud: gRPC and REST for performance and compatibility
- Netflix: GraphQL for flexible mobile application data requirements
- Uber: gRPC for communication between microservices
Can You Use Multiple Protocols?
Yes. A single platform can expose different protocols to different consumers:
- REST for external and public clients
- GraphQL for mobile applications
- gRPC for internal services
This approach lets each client use the protocol that best matches its requirements while the services share the same business logic and data layer.
Conclusion
REST, GraphQL, and gRPC are tools for different jobs:
- REST is universal, simple, and easy to cache.
- GraphQL gives clients control over the response shape.
- gRPC provides efficient communication and native streaming for internal services.
Modern PetstoreAPI implements all three so you can compare equivalent operations across protocols. Explore its REST documentation, GraphQL schema, and gRPC Protocol Buffer definitions to understand how each interface works.
Use Apidog to test each protocol, compare implementations, and verify that a multi-protocol API returns consistent results.
The best protocol is the one that solves your specific problem. Start with the client and service requirements, then choose the simplest protocol that meets them.
FAQ
Can I use REST and GraphQL together?
Yes. Many APIs expose both. Use REST for simple, predictable operations and GraphQL for complex or variable data requirements. GitHub uses this approach.
Is gRPC replacing REST?
No. gRPC is commonly used for internal microservice communication, while REST remains widely used for public APIs because of its compatibility and tooling.
Which protocol is fastest?
gRPC is generally the fastest of the three because it uses Protocol Buffers and HTTP/2. However, network latency and service behavior often matter more than serialization speed, so benchmark your actual workload.
Should I migrate from REST to GraphQL?
Only migrate when REST is causing a concrete problem, such as significant over-fetching or under-fetching. Do not migrate solely because GraphQL is popular.
Can browsers use gRPC?
Not directly in the same way as native gRPC clients. Browser applications generally need grpc-web, which adds complexity. For browser clients, REST or GraphQL is often simpler.
How does Modern PetstoreAPI keep all three protocols in sync?
The protocols use a shared business logic layer. REST, GraphQL, and gRPC act as thin adapters over the same core API.
Which protocol should startups use?
Start with REST unless you already have a clear reason to choose something else. REST is simple, well understood, and supported by mature tooling. Add GraphQL or gRPC when the requirements justify them.
Does Apidog support all three protocols?
Yes. Apidog supports REST through OpenAPI, GraphQL, and gRPC in one tool, making it possible to test multi-protocol APIs such as Modern PetstoreAPI.
Top comments (0)