A sound implementation does not ask users to refresh until it works. Each phase has an input, an output, a timeout, and a terminal state. Offset shifts after inserts and creates duplicates or gaps. A cursor encodes the final ordering tuple such as createdAt and ID and queries with strict comparison.
An API contract includes units, defaults, idempotency, error classes, and version windows—not only field types. Clients distinguish retryable, user-action, and permanent outcomes to avoid duplicate side effects.
Define the system contract first
This capability crosses clients, networks, and servers, so a local optimization can create a system failure. Decisions must constrain both endpoints, persisted truth, and operating budgets together.
- Use immutable order plus unique ID, version and sign cursors bound to filters, and return next/prev plus hasMore without exposing mutable internals.
- Bound every input by size, count, and time, returning a stable actionable error code when a budget is exceeded.
- Use explicit capability negotiation so older clients receive an explained fallback instead of a half-working state.
The delivery standard for Stable Cursor Pagination Without Duplicates or Gaps During Changes is a usable normal path, convergent failures, bounded resources, and a state users can understand. The result is a production capability that can be explained, degraded safely, and rolled back—not a demo that works once.
What can break that contract
Failure and success must share one state model. An error toast that neither releases resources nor propagates a terminal state leaves dirty work for the next recovery attempt.
- Second-resolution createdAt skips tied records, while a cursor unbound from actor and filters can probe another dataset.
- A stale response arriving after a new task can overwrite healthy state or restart cancelled work without version fencing.
- An untested fallback receives all traffic during a primary failure and becomes the slower, more expensive bottleneck.
How to test the contract line by line
Do not stop verification when the final action succeeds. Count side effects, measure wait time, inspect privacy, and prove the next run begins from a clean baseline.
- Insert, delete, and modify around every boundary during forward and reverse scans; results must avoid duplicates under documented snapshot or live semantics.
- Race refresh, cancel, timeout, and remote completion in one scheduling window; assert one terminal state and one side effect.
- Use fault injection to prove alerts precede user reports and operators can locate the failing phase from bounded evidence.
A capability becomes maintainable when it degrades safely, repetition adds no side effects, and its signals reveal a fault before user reports do.