APIs that survive change
Evolve a public interface while clients, jobs, and deployments move at different speeds.
BY THE END, YOU CAN
- Recognize backward-incompatible changes
- Define idempotency scope and conflict behavior
- Design pagination and schema evolution deliberately
Diagram description: Old client → POST /jobs; New client → POST /jobs; POST /jobs → Jobs; Idempotency-Key → POST /jobs
Your callers deploy on their own schedule
An API is a promise made to clients you may not update at the same time.
Removing a field, changing its type, or assigning a new meaning can break those clients. Even adding an enum value can break consumers that assume the set is exhaustive. Prefer explicit compatibility rules, documented defaults, and a deprecation period when a breaking change is necessary.
For queued work, remember that stored jobs may use an older payload shape long after the code that created them has been replaced.
Make repeated requests meaningful
An idempotency key lets a client identify retries of one intended operation.
Scope it to the appropriate tenant or caller and persist the relationship between key, request meaning, and result. Reusing the same key with a different payload should have defined conflict behavior. Concurrent submissions with one key need a database-enforced uniqueness rule.
Document how long records are retained; after expiration, a retry may be treated as new. The key is a protocol, not a magic header that automatically makes all downstream effects occur once.
Design for moving collections
Offset pagination is simple but can skip or repeat records when inserts and deletes shift positions between requests.
Cursor pagination uses a stable ordering and a continuation boundary, often including a unique tie-breaker. It still needs documented consistency expectations when data changes. Cap page sizes and avoid exposing internal implementation details unnecessarily in cursors.
For schema changes, deploy compatible readers and writers in stages: add a field, support both shapes, backfill where needed, then remove old behavior only when consumers have moved.
COMMON FAILURE MODE
An idempotency cache with no durable uniqueness or payload check can create duplicates under concurrency or silently reuse the wrong result.
TRY IT YOURSELF
Define what Relay returns when the same idempotency key is submitted twice with the same payload, then with a different payload. Include retention and concurrent requests.
Make the call in the laboratory.
The two-question checkpoint, your notes, and your saved progress are in the laboratory. Free, with no account.
Open in the laboratory ↗CONNECT IT TO RELAY
Add a versioned Relay payload and write a compatibility plan for introducing a new required concept without immediately breaking old jobs.