Top REST API Design Pitfalls by Victor Rentea
Abstract
Breaking change your API:
- Major versioning sucks: avoid it.
- Use automated contract testing:
- Detect accidental changes in a contract.
- Check current contract (
/v3/api-docs) vs the one saved on git yesterday.- Use openapi-diff.
- Failed CI on mismatch of consumed ↔ provided contract.
- Auto-upgrade to newer versions of API client libraries.
- Use
renovate/dependabotsubmits PRs to upgrade version.Expose internal Domain model:
- Domain model freezes because clients depend on it, i.e. cannot make changes on your domain models.
- Security risk as it can expose excessive data.
- Domain pollution with presentation stuff like
@JsonIgnore.Force your clients to remote-call-in-loop:
- API design can hurt performance.
- E.g. only expose get-one-by-id
GET /product/{id}⇒ clients will dofor (id in list10k) { yourApi.get(id) }.- Expose a bulk retrieve:
GET /products?id=1,3,5(⚠️ URL.length ⇐ 2k chars)POST /products/get-many + body- Don’t forget to add traces, especially for microservice architecture, to understand the response latency.
Reuse same DTO for
POST/PUT/GET:
- Can be misleading for clients, as they won’t know which fields to set, etc…
- It will couple the endpoints → introduce change ripple.
- The speaker suggests using
Request/Responsesuffixes instead ofDTO.
- E.g.
GetItemResponse get(id),void create(CreateItemRequest).- CQRS at the API level.
- A tip for performance: use a repository that returns only the desired data directly in the controller, instead of the whole object.
Large
PUTorPATCH,CRUDforever!
- Large
PUTcan create concurrent updates, which can cause data loss by blind overwrite.- Instead, split the updates by which fields are updated on the user flow.
- E.g.
PUT /items/13/details,PUT /items/13/deactivate,PUT /item/13/cost,PUT /items/13/sell- ✅
- Intentional API for clients.
- Less concurrency risk (finer-grained).
- Simpler on the server (no need to diff).
- ❌
- Requires user research.
- More APIs.
- More screens → full-stack.
Religious REST fallacy:
- Do not follow REST design blindly as it can lead to:
- unbalanced complexity;
- limiting API semantics (CRUD).
- Enhance it with:
- sub-resources, e.g.
GET or PUT /items/13/cost;- actions:
POST /items/13/sell.- Try to stick to REST for as long as it’s decent.
- See REST next level - crafting domain driven web APIs.
- Avoid
PATCH, not useful at all, and lacks semantics.