Stackbook Logo
architecture-descriptionestablished · low operational burden

Pagination (Cursor vs Offset)

Also known as: cursor-pagination, offset-pagination, keyset-pagination

Intent

Return large result sets in pages efficiently, avoiding performance cliffs and consistency issues.

Problem

Offset pagination (LIMIT/OFFSET) gets slower with each page, skips/duplicates on concurrent writes. Cursor pagination is consistent and fast.

Forces

  • Result sets can be millions of rows
  • Clients need predictable performance per page
  • Concurrent writes must not cause skipped/duplicate items
  • API must be simple for clients

Solution

✓ When to Use

  • Any list endpoint returning >100 items
  • Concurrent writes to collection
  • Performance matters (mobile, infinite scroll)

✗ When Not to Use

  • Small, static datasets (<100 items)
  • Random access required (page 50 directly)
  • Simple admin tools

Pros

  • +Constant performance: page 1 = page 10000
  • +Consistent: no skips/duplicates on writes
  • +Scales: works at billions of rows
  • +Stateless: cursor encodes position

Cons

  • No random access (can't jump to page 50)
  • Cursor opaque: client can't construct
  • Bidirectional complex (reverse sort)
  • Sort key must be unique + immutable

Cost Profile

Infrastructure

None — query pattern

Operational

Low — index on sort keys

Cognitive

Medium — cursor encoding, sort keys

Failure Modes

  • Non-unique sort key → unstable ordering, duplicates

  • Mutable sort key (updated_at) → items move between pages

  • Cursor tampering → invalid decode, 400

  • Reverse pagination without reverse index → slow

Real-World Examples

Alternatives

  • offset-pagination
  • page-numbers
  • infinite-scroll
  • load-more

Related Patterns

  • api-design
  • cursor-pagination
  • keyset-pagination
  • database-indexing
  • ulid

Competency Domains

distribution communicationdata statereliability opseconomics evolution