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
You’re building an API. Should you use REST, GraphQL, or gRPC? Each protocol has passionate advocates claiming theirs is best. The truth: they’re all good at different things.
REST is universal and simple. GraphQL gives clients control over data fetching. gRPC is fast and efficient for internal services. The best choice depends on your use case, not which protocol is “better.”
Most APIs pick one protocol and stick with it. Modern PetstoreAPI takes a different approach: it implements REST, GraphQL, and gRPC, showing how the same pet store API works across all three protocols.
In this guide, you’ll learn the strengths and weaknesses of each protocol, see real examples from Modern PetstoreAPI, and discover how to choose the right protocol for your needs.
REST: The Universal Standard
REST (Representational State Transfer) is the most common API protocol.
How REST Works
Resources are accessed via URLs with 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
1. Universal compatibility
Every programming language has HTTP libraries. Browsers, curl, Postman—everything works with REST.
2. Simple to understand
URLs represent resources. HTTP methods represent actions. The mental model is straightforward.
3. Cacheable
HTTP caching works out of the box. GET requests can be cached by browsers, CDNs, and proxies.
4. Stateless
Each request is independent. No session state on the server.
5. Great tooling
OpenAPI specs, Swagger UI, API testing tools—REST has the best ecosystem.
REST Weaknesses
1. Over-fetching
You get all fields even if you only need one:
// 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": [...]
}
2. Under-fetching (N+1 problem)
To get a pet and its orders, you need multiple requests:
GET /pets/123 # Get pet
GET /pets/123/orders # Get orders
GET /orders/456/items # Get order items
3. Versioning complexity
Breaking changes require new API versions (/v1, /v2).
4. No real-time updates
REST is request-response. For real-time data, you need polling or WebSockets.
When to Use REST
- Public APIs (maximum compatibility)
- Simple CRUD operations
- When caching is important
- When you need broad tool support
- Mobile apps with predictable data needs
Modern PetstoreAPI REST implementation
GraphQL: Flexible Data Fetching
GraphQL lets clients specify exactly what data they need.
How GraphQL Works
Single endpoint with a query language:
query {
pet(id: "019b4132-70aa-764f-b315-e2803d882a24") {
name
species
orders {
id
total
items {
product
quantity
}
}
}
}
Response:
{
"data": {
"pet": {
"name": "Fluffy",
"species": "CAT",
"orders": [
{
"id": "order-123",
"total": 49.99,
"items": [
{"product": "Cat food", "quantity": 2}
]
}
]
}
}
}
GraphQL Strengths
1. No over-fetching
Clients request only the fields they need:
query {
pet(id: "019b4132-70aa-764f-b315-e2803d882a24") {
name # Only get the name
}
}
2. No under-fetching
Get related data in one request:
query {
pet(id: "019b4132-70aa-764f-b315-e2803d882a24") {
name
orders {
items {
product
}
}
}
}
No N+1 problem.
3. Strong typing
GraphQL schemas are strongly typed. Clients know exactly what’s available.
4. Introspection
Clients can query the schema to discover available operations:
query {
__schema {
types {
name
fields {
name
type
}
}
}
}
5. Single endpoint
All operations go through one URL: /graphql
GraphQL Weaknesses
1. Complexity
GraphQL is harder to learn than REST. Queries, mutations, subscriptions, resolvers—there’s more to understand.
2. Caching is harder
HTTP caching doesn’t work well. You need custom caching strategies.
3. Over-querying risk
Clients can write expensive queries:
query {
pets {
orders {
items {
product {
reviews {
author {
pets {
# Infinite depth!
}
}
}
}
}
}
}
}
You need query depth limits and complexity analysis.
4. File uploads are awkward
GraphQL wasn’t designed for file uploads. You need workarounds.
5. Monitoring is harder
All requests go to /graphql. You can’t monitor by URL.
When to Use GraphQL
- Mobile apps (reduce bandwidth)
- Complex data requirements
- When clients need flexibility
- Internal APIs with known clients
- When you want to avoid versioning
Modern PetstoreAPI GraphQL implementation
gRPC: High-Performance RPC
gRPC uses Protocol Buffers for efficient binary communication.
How gRPC Works
Define services 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;
}
Client code (generated):
client := pb.NewPetServiceClient(conn)
pet, err := client.GetPet(ctx, &pb.GetPetRequest{
Id: "019b4132-70aa-764f-b315-e2803d882a24",
})
gRPC Strengths
1. Performance
Protocol Buffers are smaller and faster than JSON:
- 3-10x smaller payloads
- 20-100x faster serialization
2. Streaming
Built-in support for server streaming, client streaming, and bidirectional streaming:
rpc WatchPets(WatchPetsRequest) returns (stream Pet);
3. Strong typing
Protocol Buffers enforce types at compile time.
4. Code generation
Generate client and server code in 10+ languages from .proto files.
5. HTTP/2
Multiplexing, header compression, and server push.
gRPC Weaknesses
1. Not browser-friendly
Browsers don’t support HTTP/2 bidirectional streaming. You need grpc-web (a workaround).
2. Not human-readable
Protocol Buffers are binary. You can’t curl a gRPC endpoint and read the response.
3. Harder to debug
Binary protocols are harder to inspect than JSON.
4. Less tooling
Fewer tools compared to REST. No equivalent of Swagger UI.
5. Steeper learning curve
Protocol Buffers, code generation, and gRPC concepts take time to learn.
When to Use gRPC
- Microservices communication
- High-performance requirements
- Real-time streaming
- Internal APIs (not public)
- Polyglot environments (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 only |
| Data Format | JSON (usually) | JSON | Protocol Buffers (binary) |
| Endpoints | Multiple (/pets, /orders) |
Single (/graphql) |
Service methods |
| Over-fetching | Common | Rare | N/A (you define messages) |
| 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 (need 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 is unique: it implements the same pet store API in 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:
pet, err := client.GetPet(ctx, &pb.GetPetRequest{
Id: "019b4132-70aa-764f-b315-e2803d882a24",
})
All three return the same pet data.
Why Implement All Three?
1. Learn by comparison
See how the same operations work in different protocols.
2. Choose the right tool
Use REST for public endpoints, GraphQL for mobile apps, gRPC for internal services.
3. Migration path
Start with REST, add GraphQL or gRPC later without rewriting everything.
4. Reference implementation
Modern PetstoreAPI shows production-ready patterns for all three protocols.
Check the protocol comparison guide for detailed examples.
Testing Multi-Protocol APIs with Apidog
Apidog supports REST, GraphQL, and gRPC in one tool.
Testing REST
Import OpenAPI spec and run automated 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 GraphQL queries and validate responses:
query GetPet($id: ID!) {
pet(id: $id) {
id
name
species
}
}
Apidog validates against the GraphQL schema.
Testing gRPC
Import .proto files and test gRPC services:
service: PetService
method: GetPet
request: { "id": "019b4132-70aa-764f-b315-e2803d882a24" }
Apidog generates requests from Protocol Buffer definitions.
Cross-Protocol Testing
Test that all three protocols return consistent data:
- Call REST endpoint
- Call GraphQL query
- Call gRPC method
- Compare responses
Apidog helps ensure your multi-protocol API stays consistent.
Choosing the Right Protocol
Use this decision tree:
Is this a public API?→ Yes: Use REST (maximum compatibility) → No: Continue
Do you need real-time streaming?→ Yes: Use gRPC or WebSocket → No: Continue
Do clients need flexible data fetching?→ Yes: Use GraphQL → No: Continue
Is performance critical (microservices)?→ Yes: Use gRPC → No: Use REST (simplest option)
Real-World Examples
- Stripe: REST (public API, simple, cacheable)
- GitHub: REST + GraphQL (REST for public, GraphQL for complex queries)
- Google Cloud: gRPC + REST (gRPC for performance, REST for compatibility)
- Netflix: GraphQL (mobile apps need flexible data)
- Uber: gRPC (microservices communication)
Can You Use Multiple Protocols?
Yes! Modern PetstoreAPI shows how. Common patterns:
- REST for public API
- GraphQL for mobile apps
- gRPC for internal microservices
Each protocol serves different clients with different needs.
Conclusion
REST, GraphQL, and gRPC aren’t competitors—they’re tools for different jobs. REST is universal and simple. GraphQL gives clients control. gRPC is fast and efficient.
Modern PetstoreAPI implements all three, showing how the same API works across protocols. You can explore the REST documentation, GraphQL schema, and gRPC proto files to see production-ready examples.
Use Apidog to test all three protocols, compare implementations, and ensure consistency across your multi-protocol API.
The best protocol is the one that solves your specific problem. Modern PetstoreAPI gives you the knowledge to choose wisely.
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 for internal microservices. REST remains the standard for public APIs due to better compatibility and tooling.
Which protocol is fastest?
gRPC is fastest due to Protocol Buffers and HTTP/2. But for most APIs, the difference doesn’t matter—network latency dominates.
Should I migrate from REST to GraphQL?
Only if you have the over-fetching/under-fetching problem. Don’t migrate just because GraphQL is trendy.
Can browsers use gRPC?
Not directly. You need grpc-web, which adds complexity. For browser clients, use REST or GraphQL.
How does Modern PetstoreAPI keep all three protocols in sync?
Shared business logic layer. REST, GraphQL, and gRPC are thin protocol adapters over the same core API.
Which protocol should startups use?
Start with REST. It’s simple, well-understood, and has great tooling. Add GraphQL or gRPC later if you need them.
Does Apidog support all three protocols?
Yes. Apidog supports REST (OpenAPI), GraphQL, and gRPC in one tool, making it easy to test multi-protocol APIs like Modern PetstoreAPI.



