Three API paradigms with very different philosophies. Here's when each one is the right tool and why copying the wrong one leads to pain.
REST: Resources and HTTP Semantics
REST treats everything as a resource with a URL, and uses HTTP verbs to express intent — GET to read, POST to create, PUT/PATCH to update, DELETE to remove. It's stateless, cacheable, and universally understood. REST is the default choice for public APIs because every language, framework, and developer already understands it. bash
# REST — resource-oriented, verb-driven GET /users/42 POST /users PATCH /users/42 DELETE /users/42/posts/7
The REST Problem: Over-fetching and Under-fetching
GraphQL exposes a single endpoint and lets clients declare exactly what data they need in a typed query language. The server returns precisely that shape — nothing more, nothing less. This eliminates over/under-fetching and is transformative for complex UIs with many data dependencies. graphql
query { user(id: "42") { name email posts(last: 5) { title createdAt } followers { count } } }
- ▸HTTP caching doesn't work natively — everything is POST to /graphql
- ▸N+1 query problems are real without DataLoader or batching
- ▸Schema design is hard to get right and painful to break once public
- ▸Excellent for frontend-heavy apps where UI teams own query shapes
- ▸Overkill for simple CRUD APIs — adds complexity without benefit
SOAP: Contracts, Envelopes, and Enterprise
The Decision Framework
- ▸Public API with unknown consumers? → REST — universal, cacheable, well-understood
- ▸Complex frontend with many data shapes per screen? → GraphQL
- ▸Internal microservices needing performance and streaming? → gRPC
- ▸Enterprise integration with formal contracts, WS-Security, or legacy systems? → SOAP
- ▸Simple CRUD with a mobile app? → REST, possibly with a BFF (Backend for Frontend) pattern