Background
PR #57 merges explore_listings (metadata-repo) and legacy deployments into a single /api/store/appchains endpoint. The current pagination uses offset-based slicing after fetching limit + offset rows from each table.
Problem: For high page offsets (e.g. page 100, limit 50), fetchLimit becomes 5000, loading up to 10,000 rows into memory before merging and slicing. This degrades linearly with page depth.
Ref: #57 (comment)
Proposed Solution
Migrate to cursor-based pagination:
- Use
created_at (or a composite created_at + id) as the cursor key
- Client sends
?cursor=<opaque_token>&limit=50 instead of ?offset=N
- Server decodes cursor →
WHERE created_at < ? ORDER BY created_at DESC LIMIT ?
- Response includes
next_cursor for the client to fetch the next page
Benefits
- O(1) per page regardless of depth (no large offset scans)
- Works naturally with the merged listings + deployments pattern (interleave by
created_at)
- Stable pagination even when new items are inserted
Files to Change
platform/server/routes/store.js — /api/store/appchains endpoint
platform/server/db/listings.js — getListings() query
platform/server/db/deployments.js — getActiveDeployments() query
platform/client/ — frontend pagination components
Priority
Low — current data volume is < 100 items. This becomes relevant when listings grow to 1,000+.
Background
PR #57 merges
explore_listings(metadata-repo) and legacydeploymentsinto a single/api/store/appchainsendpoint. The current pagination uses offset-based slicing after fetchinglimit + offsetrows from each table.Problem: For high page offsets (e.g. page 100, limit 50),
fetchLimitbecomes 5000, loading up to 10,000 rows into memory before merging and slicing. This degrades linearly with page depth.Ref: #57 (comment)
Proposed Solution
Migrate to cursor-based pagination:
created_at(or a compositecreated_at + id) as the cursor key?cursor=<opaque_token>&limit=50instead of?offset=NWHERE created_at < ? ORDER BY created_at DESC LIMIT ?next_cursorfor the client to fetch the next pageBenefits
created_at)Files to Change
platform/server/routes/store.js—/api/store/appchainsendpointplatform/server/db/listings.js—getListings()queryplatform/server/db/deployments.js—getActiveDeployments()queryplatform/client/— frontend pagination componentsPriority
Low — current data volume is < 100 items. This becomes relevant when listings grow to 1,000+.