APIs & Integration
The contracts between services — REST, gRPC, GraphQL — and how to evolve them without breaking callers.
By the end of this lesson, choose an API style and design contracts that can evolve safely.
An API is a contract: it defines what one service promises to another. The style you choose shapes coupling, performance, and evolvability. REST (resources over HTTP) is ubiquitous and cache-friendly. gRPC (binary, HTTP/2, schema-first) is fast and strongly typed, ideal service-to-service. GraphQL lets clients request exactly the fields they need, avoiding over- and under-fetching.
Three contract styles
- REST suits public, cacheable APIs; gRPC suits internal service-to-service calls; GraphQL suits aggregating data for varied clients.
flowchart TB rest[REST: resources + verbs over HTTP] --> use1[Public, cacheable APIs] grpc[gRPC: schema-first binary over HTTP/2] --> use2[Internal service-to-service] gql[GraphQL: client-specified queries] --> use3[Aggregating varied clients]
The hardest part isn't the first version — it's evolving without breaking existing callers. Rules: make additive, backward-compatible changes (new optional fields, never remove or repurpose); version explicitly when you must break (URL or header); and treat the schema as a contract others depend on. A gateway (BFF) often fronts these APIs to handle auth, rate limiting, and aggregation.
Breaking change to a live contract
- Trigger
- Removing/renaming a field or tightening validation callers relied on.
- Symptom
- Downstream clients break in production, often silently.
- Blast radius
- Every consumer of the API.
- Mitigation
- Additive-only changes, explicit versioning, contract tests, deprecation windows.
Deep dive: Partial Failure
What makes an API change backward-compatible?
It only adds optional elements and never removes, renames, or repurposes existing ones, so current callers keep working unchanged.