API Design Patterns Every Backend Engineer Should Know
API Design Patterns Every Backend Engineer Should Know
A well-designed API is a product. Developers are your users. Confusing endpoints, inconsistent naming, and cryptic errors drive them away.
Resource naming
Use nouns, not verbs:
GET /users # list users
POST /users # create user
GET /users/:id # get one user
PATCH /users/:id # partial update
DELETE /users/:id # delete user
Nest related resources: GET /users/:id/orders
Pagination
Cursor-based pagination scales better than offset:
{
"data": [...],
"cursor": "eyJpZCI6MTIzfQ",
"has_more": true
}
Offset pagination (?page=3&limit=20) breaks when data changes between requests and performs poorly on large tables.
Versioning
Version in the URL path (/v1/users) for breaking changes. Avoid versioning every minor addition. Deprecate old versions with clear timelines and migration guides.
Error responses
Return consistent error shapes:
{
"error": {
"code": "VALIDATION_FAILED",
"message": "Email is required",
"field": "email"
}
}
Use proper HTTP status codes: 400 for client errors, 401/403 for auth, 404 for missing resources, 409 for conflicts, 429 for rate limits, 500 for server errors.
Idempotency
For POST endpoints that create resources or charge money, accept an Idempotency-Key header. If the client retries with the same key, return the original response instead of creating duplicates.
Documentation
OpenAPI specs aren't optional for public APIs. Generate them from code or maintain them as the source of truth. Include example requests and responses for every endpoint.
Good APIs are boring in the best way — predictable, consistent, and easy to integrate.