Pagination and Live Queries
Define a strategy for using live queries when the module cannot keep the full dataset locally hydrated.
The current local table strategy works best when the relevant dataset is already loaded into the collection.
That breaks down for on-demand mode, paginated lists, and infinite loading. In those cases the collection is not a full mirror of the server dataset. It is a local cache of the currently loaded window.
The problem
With a fully local collection, live queries can freely filter and sort because all rows are present.
With paginated or infinite loading:
- only part of the dataset is present locally
- local sorting only reflects the loaded window
- local filtering can hide missing rows that were never loaded
- row counts and page boundaries still belong to the server
Strategy
Treat this as a separate mode instead of stretching the current local table strategy too far.
Full local mode
- all relevant rows are loaded
- local filters and sorting are authoritative for the current screen
- live queries operate on the full working set
Windowed local mode
- only the active subset or loaded pages are present
- server filters, sorting, and pagination remain authoritative
- live queries operate on the loaded window to keep the UI reactive
- additional pages append or replace rows in the collection
What Tulip should provide
- a data-table strategy that understands server pagination plus local reactivity
- stable subset query keys so loaded windows do not collide
- reset behavior when filter or sorting inputs change
- deduplication by row id when pages append into the same collection
- a clear distinction between
loadedRowCountand total serverrowCount
Recommended behavior
For paginated and infinite screens:
- let the server own filter, sort, pagination, and total count semantics
- let the collection own optimistic row updates and reactive rendering for loaded rows
- reset the loaded window whenever the query identity changes
- keep shared table and dataset APIs on
{ page, limit }; hide provider-native cursors inside provider query code when needed
Why this matters
This is the piece that decides whether Local can scale beyond detail screens. If we solve windowed live queries well, then large modules can still benefit from optimistic updates without pretending the whole dataset lives in memory.
Open questions
- should Tulip expose a dedicated
windowedtable strategy, or extend the existinglocalone? - how long should loaded pages stay in memory?
- what is the expected behavior when a mutation changes whether a row belongs to the current loaded subset?