In This Guide
Key Takeaways
- REST is the right default: REST is the right choice for most public APIs, team APIs, and third-party integrations. It is the most widely understood protocol, the most widely supported by HTTP clients and tooling, and requires no specialized client libraries.
- GraphQL solves the N+1 and over-fetching problems: GraphQL lets clients specify exactly what data they need, eliminating over-fetching (REST returns the full object even when you need two fields) and N+1 queries (nested resource fetching). The cost is server complexity.
- gRPC is for internal microservices: gRPC uses Protocol Buffers (binary serialization) and HTTP/2, providing 5-10x better throughput than REST/JSON for high-frequency internal service calls. It is not appropriate for public APIs or browser-based clients without a translation layer.
- API contracts are more important than protocol: Whether you choose REST, GraphQL, or gRPC, the most important design decision is your API contract — the specific shapes, behaviors, and guarantees you expose to clients. Good contracts are stable, predictable, and well-documented.
Choosing between REST, GraphQL, and gRPC is not a religious debate — it is an engineering trade-off based on your specific use case, your clients, your team's skills, and your performance requirements.
This guide covers when each protocol excels, what the actual design decisions look like in practice, and how to make the right choice for your specific project — not based on what is trendy, but on what solves your actual problems.
REST: The Default Choice and Why
REST (Representational State Transfer) is an architectural style built on HTTP. Resources are identified by URLs, actions are expressed through HTTP methods (GET, POST, PUT, PATCH, DELETE), and data is exchanged in JSON format. It is not a protocol or a standard — it is a set of conventions that have become the de facto API design language.
REST strengths:
- Every HTTP client supports it natively — curl, browsers, Postman, any language's HTTP library
- Caching works naturally through HTTP cache headers (Cache-Control, ETag, Last-Modified)
- Stateless: each request contains all information needed to process it, enabling horizontal scaling
- Human-readable URLs make debugging and monitoring straightforward
- OpenAPI/Swagger spec generates client SDKs, documentation, and mock servers automatically
REST limitations:
- Over-fetching:
GET /users/123returns the full user object even if you only need the name - Under-fetching / N+1:
GET /users/123thenGET /users/123/poststhenGET /posts/456/comments— multiple round trips for related data - Versioning complexity: Breaking changes require URL versioning (/v1, /v2) or header versioning, creating parallel API surfaces to maintain
GraphQL: When Flexibility Justifies Complexity
GraphQL is a query language for APIs developed by Facebook. Clients send a query specifying exactly the fields they need, and the server returns precisely that data — no more, no less. A single GraphQL endpoint replaces dozens of REST endpoints.
# GraphQL query — client specifies exactly what it needs
query {
user(id: "123") {
name
email
posts(first: 5) {
title
publishedAt
comments { count }
}
}
}This single query replaces: GET /users/123, GET /users/123/posts?limit=5, and GET /posts/{id}/comments/count for each post — multiple REST requests collapsed into one.
GraphQL strengths: eliminates over-fetching and under-fetching, type system enables excellent developer tooling (auto-complete, type checking, schema introspection), single endpoint simplifies client routing.
GraphQL limitations: N+1 problem on the server side (resolver functions for nested fields can trigger many database queries — requires DataLoader batching), complex caching (the single endpoint makes HTTP caching less effective), higher server complexity than equivalent REST endpoints, no native file upload support.
When to use GraphQL: complex frontends with diverse data needs (mobile + web + embedded), products that want to expose a public API where clients should control data shape, and organizations where the front-end and back-end teams are decoupled.
gRPC: The Microservices Protocol
gRPC is a high-performance RPC framework developed by Google. It uses Protocol Buffers (protobuf) for binary serialization and HTTP/2 for transport. gRPC is 5-10x faster than REST/JSON for equivalent operations and supports streaming (client streaming, server streaming, bidirectional streaming).
You define your API in a .proto file:
service UserService {
rpc GetUser (GetUserRequest) returns (User);
rpc ListUsers (ListUsersRequest) returns (stream User);
}
message GetUserRequest { string user_id = 1; }
message User {
string id = 1;
string email = 2;
string name = 3;
}The protobuf compiler generates client and server code in 10+ languages. The generated types are strongly typed — no manual JSON parsing, no runtime type errors.
gRPC strengths: binary serialization (2-10x smaller payloads than JSON), HTTP/2 multiplexing (multiple requests over one connection), streaming support, strong typing from protobuf.
gRPC limitations: no native browser support (requires gRPC-Web proxy for browser clients), not human-readable (binary wire format is harder to debug), protobuf schema management requires tooling, smaller ecosystem than REST/JSON.
When to use gRPC: internal microservice-to-microservice communication where throughput and latency matter, streaming data scenarios (real-time data feeds, large file transfers), and polyglot service architectures where generated client SDKs in multiple languages are valuable.
REST Best Practices That Matter
These are the conventions that make REST APIs predictable, maintainable, and client-friendly:
Resource naming: Use plural nouns for collection resources (/users, /orders). Individual resources use the ID (/users/123). Nested resources represent relationships (/users/123/orders). Use kebab-case for multi-word paths (/payment-methods).
HTTP method semantics:
- GET — retrieve, safe, idempotent, cacheable
- POST — create, not idempotent
- PUT — replace entire resource, idempotent
- PATCH — partial update, idempotent
- DELETE — remove, idempotent
Status codes: 200 OK, 201 Created (POST success), 204 No Content (DELETE success), 400 Bad Request (invalid input), 401 Unauthorized (not authenticated), 403 Forbidden (authenticated but not authorized), 404 Not Found, 409 Conflict (duplicate create), 422 Unprocessable Entity (validation error), 429 Too Many Requests (rate limited), 500 Internal Server Error.
Consistent error responses:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Email address is invalid",
"field": "email",
"request_id": "req_abc123"
}
}Include a request_id in every response. This enables customers to reference specific API calls in support tickets and enables you to trace requests through your logging system.
API Versioning: The Three Approaches
Every public API eventually needs breaking changes. How you handle versioning determines how painful those changes are for your clients.
URL versioning (/v1/users, /v2/users) is the most common and most visible approach. Clients explicitly request a version. Old versions can be maintained in parallel. Downside: proliferates URL patterns and requires maintaining multiple API versions simultaneously.
Header versioning (Accept: application/vnd.myapi.v2+json) keeps URLs clean but is invisible in browser address bars and harder to test with simple curl commands.
Additive-only evolution avoids versioning by making only backwards-compatible changes: add new fields (never remove), add new endpoints (never delete old ones), add new optional parameters (never make existing parameters required). This approach works until a genuinely breaking change is required, at which point you need a version bump regardless.
Practical recommendation: use URL versioning for public APIs. Use additive-only evolution as long as possible before incrementing the version. When you do release v2, maintain v1 for at least 12 months with a clear deprecation notice and migration guide.
Frequently Asked Questions
When should I use GraphQL instead of REST?
Use GraphQL when your clients have highly variable data needs (mobile apps need less data than desktop), when you are building a product API that external developers will consume, or when your front-end and back-end teams are decoupled and the front-end team should control data fetching. Do not use GraphQL for simple CRUD APIs, when caching is critical, or when your team does not have GraphQL experience.
Is gRPC faster than REST?
Yes, significantly for equivalent operations. gRPC uses Protocol Buffers (binary serialization) and HTTP/2, which provides 5-10x better throughput and lower latency than REST/JSON over HTTP/1.1. The benefit is most pronounced for high-frequency internal service calls with small payloads. For browser-based APIs and external integrations, REST/JSON is still the standard — gRPC-Web exists but adds complexity.
How do I document my REST API?
Use the OpenAPI (formerly Swagger) specification to define your REST API. OpenAPI is a JSON or YAML document that describes all endpoints, request/response schemas, authentication methods, and examples. The OpenAPI spec can generate interactive documentation (Swagger UI, Redoc), client SDK code in 40+ languages, mock servers for testing, and server stub code. Most frameworks have libraries that auto-generate OpenAPI specs from your route definitions.
What is API rate limiting and how do I implement it?
Rate limiting prevents clients from making too many API requests, protecting your service from abuse and ensuring fair usage. Common rate limiting strategies: fixed window (X requests per minute), sliding window (more accurate but more complex), and token bucket (allows bursts up to a limit). Implement rate limiting at the API gateway level (AWS API Gateway, Kong, nginx) rather than in application code. Return 429 Too Many Requests when limits are exceeded, with a Retry-After header indicating when the client can try again.
API design is a core skill for every backend developer. Get the skills.
Join professionals from Denver, NYC, Dallas, LA, and Chicago for two days of hands-on AI and tech training. $1,490. October 2026. Seats are limited.
Reserve Your SeatNote: Information in this article reflects the state of the field as of early 2026. Technology evolves rapidly — verify specific details directly with vendors before making decisions.