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
/dependabot
submits 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
/Response
suffixes 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
PUT
orPATCH
,CRUD
forever!
- Large
PUT
can 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.