Pagination pattern defined and consistent
Why it matters
An API where /api/users uses cursor-based pagination and /api/orders uses offset/limit forces every consumer to write different pagination logic per endpoint. Worse, an endpoint with no pagination at all returns unbounded result sets that will eventually OOM the server or time out for large collections. iso-25010:2011 compatibility.interoperability is directly impacted: a generic list component cannot be built once and reused, and any SDK wrapping the API must special-case every list endpoint.
Severity rationale
High because inconsistent pagination patterns prevent generic client-side list handling and unbounded collections create reliability failures at scale.
Remediation
Define one pagination response shape as a generic type and apply it to every list endpoint:
interface PaginatedResponse<T> {
data: T[]
meta: {
page: number
limit: number
total: number
totalPages: number
}
}
// Use identically across all list endpoints:
// GET /api/users?page=1&limit=20
// GET /api/orders?page=2&limit=10
// Same envelope, same parameter names
Enforce a maximum page size (100 items) server-side to prevent consumers from accidentally requesting unbounded results. See the query-param-naming check for consistent parameter naming across these endpoints.
Detection
-
ID:
pagination-contract -
Severity:
high -
What to look for: Examine all list endpoints. Check whether a consistent pagination pattern is defined and used across all of them. Look for: offset-based (
page/limitwithtotal), cursor-based (cursor/limitwithnextCursor), or keyset pagination. Check that the pagination metadata shape is consistent:{ data: [...], meta: { page, limit, total } }or{ data: [...], pageInfo: { hasNextPage, endCursor } }. Compare at least 2 list endpoints to verify they use the same pattern. -
Pass criteria: List all endpoints that return collections. All list endpoints use the same pagination pattern (same parameter names, same response metadata shape). The pagination approach is appropriate for the data (cursor-based for real-time feeds, offset-based for static lists). A maximum page size is enforced with no more than 100 items per page default.
-
Fail criteria: List endpoints use different pagination patterns (one uses offset/limit, another uses cursor-based, another has no pagination). Or pagination metadata shapes differ across endpoints.
-
Skip (N/A) when: Fewer than 2 list endpoints exist, or all collections are known to be small (under 50 items by design).
-
Detail on fail: Note the inconsistency (e.g., "
GET /api/usersuses cursor-based pagination withnextCursor, butGET /api/ordersusespage/limitwith total count, andGET /api/commentshas no pagination at all."). Max 500 chars. -
Cross-reference: For query parameter naming consistency across these list endpoints, see the
query-param-namingcheck in the Naming Conventions category above. -
Remediation: Define one pagination pattern and apply it to all list endpoints:
// Standard pagination response shape: interface PaginatedResponse<T> { data: T[] meta: { page: number limit: number total: number totalPages: number } } // Use everywhere: // GET /api/users?page=1&limit=20 // GET /api/orders?page=2&limit=10 // Same shape, same parameter names
External references
- iso-25010:2011 · compatibility.interoperability — Interoperability — consistent pagination contract enables generic client code
Taxons
History
- 2026-04-18·v1.0.0·Initial import from api-design·automated