Software Engineering
API Design: REST, GraphQL, gRPC
Stripe's API is considered the industry design benchmark - not because it uses trendy technologies, but because the documentation is clear, behavior is predictable, and the API has been backward compatible since 2014. A client who integrated in 2015 still gets working code. API design is a long-term contract, not a technical choice.
- **Stripe API**: supports API versions since 2014. A client fixed a version - it works for years without forced migration. This backward compatibility is the foundation of Stripe's developer trust.
- **GitHub GraphQL API v4**: transition from REST v3 to GraphQL allowed fetching data for complex queries in one request instead of dozens. REST v3 still supported for backward compatibility.
- **Google gRPC**: all internal Google services communicate via gRPC with protobuf. Strict schema versioning prevents inter-service contract drift across thousands of services.
REST Conventions
REST (Representational State Transfer) is an architectural style defined by Roy Fielding in his 2000 dissertation. Key principles: resources identified by URLs (nouns, not verbs), HTTP methods define semantics, stateless requests (each request contains all necessary context).
HTTP methods define operation semantics: GET (read, idempotent, cacheable), POST (create, not idempotent), PUT (full replacement, idempotent), PATCH (partial update, idempotent), DELETE (remove, idempotent). URL structure: plural nouns (/orders), nested resources (/orders/123/items), filtering via query params (?status=pending).
An API endpoint for canceling an order. Which design best follows REST conventions?
GraphQL Schema
GraphQL was created by Facebook in 2012 to solve REST problems with mobile clients: over-fetching (REST returns all fields when only 3 are needed) and under-fetching (N+1 requests to get related data). The client specifies exactly what data it needs.
Schema is the contract between client and server, defines all available types and operations. Queries (read), Mutations (write), Subscriptions (real-time updates via WebSocket). Resolver - function that fetches data for a specific field. N+1 problem: without optimization, fetching 50 posts with authors makes 51 DB queries.
A GraphQL query fetches 50 posts, each with an author. Without optimization this makes 51 DB queries (1 + 50). What is the correct solution?
gRPC and Protocol Buffers
gRPC is a high-performance RPC framework from Google that uses Protocol Buffers (protobuf) for serialization and HTTP/2 for transport. Protobuf is 3-10x more compact than JSON, HTTP/2 provides multiplexing and header compression. Generated client/server code ensures type safety.
gRPC types: Unary (one request - one response, like HTTP), Server Streaming (one request - stream of responses, e.g., reading a large dataset), Client Streaming (stream of requests - one response, e.g., file upload), Bidirectional Streaming (both sides stream simultaneously, e.g., chat).
For which scenario is gRPC preferable to REST?
API Versioning
API versioning is a strategy for evolving an API without breaking changes for existing clients. Approaches: URL versioning (/v1/, /v2/), header versioning (API-Version: 2024-01), query parameter (?version=2). Stripe uses date-based header versioning - the client fixes the version at SDK initialization.
Breaking vs Non-breaking changes. Non-breaking (backward compatible): adding a new field to the response, new optional request parameter, new enum value. Breaking: removing or renaming a field, changing a field type, making an optional field required, changing URL structure. Breaking change = new API version.
Stripe's API versioning approach: clients pin a version at SDK initialization. Stripe guarantees that pinned version behavior never changes. A client integrated in 2015 still gets identical behavior. This extreme backward compatibility is the foundation of trust for the API platform.
GraphQL replaces REST and gRPC - it is the only modern approach
REST, GraphQL, and gRPC solve different problems. REST is the standard for public APIs with broad client support. GraphQL solves over-fetching/under-fetching for complex client-driven queries. gRPC is ideal for high-performance internal service communication.
Twitter uses REST for public API, GraphQL for the web client, and gRPC for internal services - all three in one company, each in its appropriate role.
A REST API changes the type of the `price` field from String ('10.00') to Number (10.00). This is:
Key Ideas
- **REST**: resource-oriented URL design, HTTP method semantics, status codes as part of the contract - simplicity and universality for public APIs.
- **GraphQL**: client-driven queries (no over/under-fetching), schema as a contract, DataLoader for N+1 - ideal when multiple client types need different data shapes.
- **gRPC**: protobuf serialization (3-10x compact), HTTP/2 streaming, generated clients - the right choice for high-performance internal service communication.
Related Topics
API Design defines the contract between services and clients:
- Microservices: Patterns — API Gateway aggregates REST/GraphQL/gRPC endpoints of microservices into a unified interface for clients
- SRE: Site Reliability Engineering — SLO for APIs: p99 latency, error rate, availability - measured and enforced through observability tools that monitor API health
Вопросы для размышления
- When does GraphQL create more problems than it solves - examples where REST would be better?
- How to ensure backward compatibility during active API development with many clients?
- gRPC's strict typing through .proto - advantage or limitation when requirements change rapidly?