REST API Design
02 / 02

Statelessness, Versioning & Query Design

Statelessness, Versioning & Query Design

Statelessness

Every request carries all context needed to process it — no server-side session state between requests. This is why auth is typically a Bearer token in the Authorization header on every request, rather than a persisted server-side session.

Versioning

/v1/users        # URL path version
Accept: application/vnd.myapi.v2+json   # content negotiation version

Adding a new optional field is safe (clients ignore what they don't recognize); removing/renaming a field or changing its type is a breaking change. Knowing this distinction determines what ships to an existing version vs. what needs a new one.

Filtering, Sorting & Pagination

GET /users?status=active&sort=-createdAt&search=ada&page=2&limit=20
GET /users?after=<cursor>&limit=20   # cursor-based, more stable under concurrent writes

PATCH Ambiguity: Omitted vs. Null

A naive merge-based PATCH can't tell "clear this field" (explicit null) from "don't touch this field" (omitted). Document the convention clearly, or use a formal patch-operation format (JSON Patch, RFC 6902) when the ambiguity matters.

Rate Limiting & Decoupling from Internals

Rate limits protect the backend from excess traffic — commonly communicated via X-RateLimit-Remaining/Retry-After headers. Avoid exposing raw database internals (auto-increment IDs, internal column names) directly — a stable API-specific shape (UUIDs, a deliberate response structure) decouples the public contract from implementation, letting the database evolve without breaking clients.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free