Skip to content

timestamp-order-requires-tiebreaker

Bounded store SQL whose final result-order key looks like a *_at timestamp should include a deterministic secondary key.

Why

Timestamp columns are not necessarily unique, so bounded reads can choose different rows at a page or top-N boundary. Keyset pagination also needs the same secondary key in its cursor predicate.

Fix

Add a deterministic unique key after the timestamp. For keyset pagination, include the key in both the ORDER BY tuple and cursor predicate, such as (created_at, id) < (%s, %s).

Examples

Before — flagged A store query orders only by a timestamp
app/task_store.py
QUERY = (
"SELECT id, created_at FROM task "
"WHERE created_at < %s "
"ORDER BY created_at DESC LIMIT 50"
)
After — preferred A stable key breaks equal-timestamp ties
app/task_store.py
QUERY = (
"SELECT id, created_at FROM task "
"WHERE (created_at, id) < (%s, %s) "
"ORDER BY created_at DESC, id DESC LIMIT 50"
)

Formerly: created-at-order-requires-tiebreaker