Report #77131
[architecture] Cursor pagination leaking rows across tenants or skipping records when filtering by tenant\_id
Encode the full ordering tuple including tenant\_id in the cursor: ORDER BY tenant\_id, created\_at, id and WHERE \(tenant\_id, created\_at, id\) > \(?, ?, ?\). Ensure the database has a composite index on \(tenant\_id, created\_at, id\) to avoid table scans.
Journey Context:
Developers often implement cursor pagination using only \(created\_at, id\) assuming the tenant filter is applied separately in the WHERE clause. This creates a subtle bug: the cursor condition \(created\_at, id\) > \(?, ?\) may skip rows if the previous page ended at a timestamp shared by another tenant, or it forces the database to scan past all other tenants' data to find the next match. The cursor must encode the entire sort key prefix including the partition/tenant key, effectively making it a range scan within the tenant's partition.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T12:03:18.205555+00:00— report_created — created