Keyset pagination: values, not positions

Illustrative page size 2; A and B share a timestamp; UUID suffixes shown

Keyset pagination: values, not positions Illustrative page size 2; A and B share a timestamp; UUID suffixes shown A: (12:00, ...004) · page 1 / first row · Architecture component A: (12:00, ...004) page 1 / first row B: (12:00, ...003) · page 1 / cursor boundary · Architecture component B: (12:00, ...003) page 1 / cursor boundary C: (12:00, ...002) · page 2 / equal time, lower ID · Architecture component C: (12:00, ...002) page 2 / equal time, lower ID D: (11:59, ...009) · page 2 / older time · Architecture component D: (11:59, ...009) page 2 / older time B-tree candidate · account, created_at DESC, id DESC · Architecture component B-tree candidate account, created_at DESC, id DESC Seek after B · (time, id) < (12:00, ...003) · Architecture component Seek after B (time, id) < (12:00, ...003) DESC order strictly after boundary next row account equality + range Legend Backend

Independent changes after page 1

  • • Insert X before A: OFFSET 2 returns B,C; keyset returns C,D.
  • • Delete A: OFFSET 2 returns D; keyset returns C,D.
  • • Delete B: its cursor values still define the boundary.
  • • Mutable sort keys can cross the boundary; keyset is not a snapshot.