TL;DR
Use REST for public APIs and simple CRUD operations. Use GraphQL when clients need flexible data fetching and you want to reduce over-fetching. Use gRPC for high-performance microservices communication. Modern PetstoreAPI implements all three protocols, letting you choose the right tool for each use case.
Introduction
When building an API, you need to decide between REST, GraphQL, or gRPC. Each protocol excels in different scenarios:
- REST is universal and straightforward.
- GraphQL gives clients fine-grained control over data fetching.
- gRPC offers high performance for internal microservices.
Most APIs stick to one protocol, but Modern PetstoreAPI implements REST, GraphQL, and gRPC, illustrating how the same API can be accessed via all three.
💡 If you’re building or testing APIs, Apidog supports REST, GraphQL, and gRPC. You can test all three protocols in one tool, compare responses, and ensure consistency across implementations.
This guide covers when to use each protocol, with real-world examples from Modern PetstoreAPI, to help you choose the right fit for your project.
REST: The Universal Standard
REST (Representational State Transfer) is the most widely used API protocol.
How REST Works
You access resources via URLs and standard HTTP methods:
GET /pets - List pets
POST /pets - Create pet
GET /pets/{id} - Get pet
PUT /pets/{id} - Update pet
DELETE /pets/{id} - Delete pet
Example request:
GET https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24
Example response:
{
"id": "019b4132-70aa-764f-b315-e2803d882a24",
"name": "Fluffy",
"species": "CAT",
"status": "AVAILABLE",
"price": 299.99
}
REST Strengths
- Universal compatibility: Every language and tool supports HTTP.
- Simple model: URLs = resources, HTTP verbs = actions.
-
Cacheable: HTTP caching for
GETrequests is automatic. - Stateless: Each request is independent.
- Great tooling: OpenAPI, Swagger UI, and API testing tools.
REST Weaknesses
-
Over-fetching: Clients receive all fields, even if only one is needed.
// You only need the name, but you get everything { "id": "019b4132-70aa-764f-b315-e2803d882a24", "name": "Fluffy", "species": "CAT", "status": "AVAILABLE", "price": 299.99, "description": "...", "images": [...], "vaccinations": [...] } -
Under-fetching (N+1 problem): Multiple requests needed for related data.
GET /pets/123 # Get pet GET /pets/123/orders # Get orders GET /orders/456/items # Get order items Versioning complexity: Breaking changes require new API versions (
/v1,/v2).No real-time updates: Need polling or WebSockets for real-time data.
When to Use REST
- Public APIs for max compatibility
- Simple CRUD operations
- When caching is important
- When broad tool support is needed
- Mobile apps with predictable data
Modern PetstoreAPI REST implementation
GraphQL: Flexible Data Fetching
GraphQL enables clients to specify exactly what data they need.
How GraphQL Works
All operations use a single endpoint and a flexible query language:
query {
pet(id: "019b4132-70aa-764f-b315-e2803d882a24") {
name
species
orders {
id
total
items {
product
quantity
}
}
}
}
Example response:
{
"data": {
"pet": {
"name": "Fluffy",
"species": "CAT",
"orders": [
{
"id": "order-123",
"total": 49.99,
"items": [
{"product": "Cat food", "quantity": 2}
]
}
]
}
}
}
GraphQL Strengths
-
No over-fetching: Clients request only what they need.
query { pet(id: "019b4132-70aa-764f-b315-e2803d882a24") { name # Only get the name } } -
No under-fetching: Nested queries fetch related data in one request.
query { pet(id: "019b4132-70aa-764f-b315-e2803d882a24") { name orders { items { product } } } } Strong typing: Schemas define available types and fields.
-
Introspection: Clients can query the schema itself.
query { __schema { types { name fields { name type } } } } Single endpoint: All requests use
/graphql.
GraphQL Weaknesses
- Complexity: More concepts to learn (queries, mutations, resolvers).
- Caching is harder: HTTP caches aren’t as effective; requires custom strategies.
-
Over-querying risk: Clients can write very expensive queries.
query { pets { orders { items { product { reviews { author { pets { # Infinite depth! } } } } } } } }Mitigate with query depth limits and complexity analysis.
File uploads are awkward: Not natively supported; requires workarounds.
Monitoring is harder: All traffic hits
/graphql, making per-operation analytics more complex.
When to Use GraphQL
- Mobile apps (to reduce bandwidth)
- Complex or flexible data requirements
- Internal APIs with known clients
- To avoid strict versioning
Modern PetstoreAPI GraphQL implementation
gRPC: High-Performance RPC
gRPC uses Protocol Buffers for efficient, strongly-typed binary communication.
How gRPC Works
Define services and messages in .proto files:
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;
}
Example client code (Go):
client := pb.NewPetServiceClient(conn)
pet, err := client.GetPet(ctx, &pb.GetPetRequest{
Id: "019b4132-70aa-764f-b315-e2803d882a24",
})
gRPC Strengths
-
Performance: Protocol Buffers are smaller and faster than JSON.
- 3-10x smaller payloads
- 20-100x faster serialization
-
Streaming: Native support for server, client, and bidirectional streaming.
rpc WatchPets(WatchPetsRequest) returns (stream Pet); Strong typing: Enforced by Protocol Buffers at compile time.
Code generation: Generate client/server stubs in 10+ languages from
.protodefinitions.HTTP/2: Multiplexing, header compression, and server push.
gRPC Weaknesses
- Not browser-friendly: Browsers can’t natively use gRPC; grpc-web is required.
- Not human-readable: Binary format instead of readable JSON.
- Harder to debug: Inspecting binary payloads is more complex.
- Less tooling: Fewer mature tools compared to REST.
- Steeper learning curve: Protocol Buffers, code generation, and gRPC concepts require ramp-up.
When to Use gRPC
- Microservices communication
- High-performance requirements
- Real-time streaming
- Internal (non-public) APIs
- Polyglot environments
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 only |
| Data Format | JSON (usually) | JSON | Protocol Buffers (binary) |
| Endpoints | Multiple (/pets) |
Single (/graphql) |
Service methods |
| Over-fetching | Common | Rare | N/A |
| Under-fetching | Common (N+1) | Rare | N/A |
| Caching | Excellent (HTTP) | Poor | Poor |
| Browser Support | Excellent | Excellent | Poor (needs grpc-web) |
| Tooling | Excellent | Good | Fair |
| Learning Curve | Easy | Medium | Hard |
| Performance | Good | Good | Excellent |
| Streaming | No (use WebSocket) | Yes (subscriptions) | Yes (native) |
| Versioning | URL or header | Schema evolution | Proto evolution |
| Best For | Public APIs, CRUD | Flexible clients | Microservices |
How Modern PetstoreAPI Implements All Three
Modern PetstoreAPI exposes the same pet store API via REST, GraphQL, and gRPC.
Same Data, Three Protocols
Get a pet by ID:
-
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 (Go):
pet, err := client.GetPet(ctx, &pb.GetPetRequest{ Id: "019b4132-70aa-764f-b315-e2803d882a24", })
All three return the same pet data.
Why Implement All Three?
- Learn by comparison: See how the same operation differs across protocols.
- Choose the right tool: Use REST for public endpoints, GraphQL for flexible clients, gRPC for internal microservices.
- Migration path: Start with REST, add GraphQL or gRPC as needed.
- Reference implementation: Production-ready patterns for all three.
See the protocol comparison guide for more.
Testing Multi-Protocol APIs with Apidog
Apidog supports REST, GraphQL, and gRPC in one testing tool.
Testing REST
Import your OpenAPI spec and define tests:
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');
});
Testing GraphQL
Write queries and validate against the schema:
query GetPet($id: ID!) {
pet(id: $id) {
id
name
species
}
}
Testing gRPC
Import .proto files and test service methods:
service: PetService
method: GetPet
request: { "id": "019b4132-70aa-764f-b315-e2803d882a24" }
Apidog generates requests directly from Protocol Buffer definitions.
Cross-Protocol Testing
To ensure consistency across protocols:
- Call the REST endpoint
- Call the GraphQL query
- Call the gRPC method
- Compare the responses
Apidog helps verify multi-protocol APIs remain consistent.
Choosing the Right Protocol
Use this decision workflow:
-
Is this a public API?
- Yes → Use REST
- No → Next question
-
Do you need real-time streaming?
- Yes → Use gRPC or WebSocket
- No → Next question
-
Do clients need flexible data fetching?
- Yes → Use GraphQL
- No → Next question
-
Is performance critical (microservices)?
- Yes → Use gRPC
- No → Use REST
Real-World Examples
- Stripe: REST (public, simple, cacheable)
- GitHub: REST + GraphQL (REST for public, GraphQL for complex queries)
- Google Cloud: gRPC + REST (gRPC for performance, REST for compatibility)
- Netflix: GraphQL (flexible data for mobile apps)
- Uber: gRPC (microservices communication)
Can You Use Multiple Protocols?
Yes. Modern PetstoreAPI demonstrates:
- REST for public APIs
- GraphQL for mobile apps
- gRPC for internal microservices
Each protocol serves different client needs.
Conclusion
REST, GraphQL, and gRPC are complementary tools:
- REST: Universal and simple
- GraphQL: Flexible data fetching for clients
- gRPC: High-performance internal APIs
Modern PetstoreAPI implements all three, so you can explore:
Use Apidog to test, compare, and keep your multi-protocol APIs consistent.
Choose the protocol that best fits your use case—Modern PetstoreAPI gives you hands-on examples for each approach.
FAQ
Can I use REST and GraphQL together?
Yes. Many APIs offer both. Use REST for simple operations and GraphQL for complex queries. GitHub does this.
Is gRPC replacing REST?
No. gRPC is used for internal microservices. REST remains the public API standard for its compatibility and tooling.
Which protocol is fastest?
gRPC is fastest due to Protocol Buffers and HTTP/2. However, for many APIs, network latency is a bigger factor than protocol speed.
Should I migrate from REST to GraphQL?
Only if you need to solve over-fetching/under-fetching problems. Don’t migrate just because GraphQL is popular.
Can browsers use gRPC?
Not directly. Browsers require grpc-web, which adds complexity. For browser clients, stick to REST or GraphQL.
How does Modern PetstoreAPI keep all three protocols in sync?
A shared business logic layer. REST, GraphQL, and gRPC are thin adapters over the same core API.
Which protocol should startups use?
Start with REST for its simplicity and tooling. Add GraphQL or gRPC later if and when you need them.
Does Apidog support all three protocols?
Yes. Apidog supports REST (OpenAPI), GraphQL, and gRPC, making it easy to test and maintain multi-protocol APIs like Modern PetstoreAPI.
Top comments (0)