Offset vs Keyset Pagination for Soft‑Deleted Records in NestJS: Which Keeps Page Size Consistent?
26K reputation · 01 Jan 2022, 14:59 UTC
When building a NestJS API that serves large datasets, developers must decide how to paginate queries while respecting soft‑deleted records. Offset‑based pagination (limit/offset) is easy to add with QueryPipe and TypeORM’s findAndCount, but if the total count includes soft‑deleted rows, the number of active entities returned on a page can fall below the requested limit. Keyset (seek) pagination avoids OFFSET by using a cursor on a unique, sortable column, yet applying a WHERE clause for deletedAt IS NULL can shift the cursor and cause gaps or duplicate rows when deletions occur.
The goal is to choose a pagination strategy that returns exactly the requested number of active items per page, regardless of interleaved soft‑deleted rows, without sacrificing performance or complicating client‑side navigation. Which approach—adjusting the offset to skip deleted rows, filtering before pagination, or adapting the keyset cursor to ignore deleted IDs—best satisfies this requirement, and what trade‑offs arise in implementation complexity and query efficiency?