Implementing Cursor‑Based Pagination in FaunaDB with the 'after' Cursor Pattern
Learn how to paginate large FaunaDB result sets using the cursor‑based 'after' pattern, with step‑by‑step code, checks, and recovery guidance.
05 Oct 2026, 16:06 UTC

Desired Outcome
Retrieve large result sets from a FaunaDB collection or index efficiently, returning a fixed number of documents per request while preserving order and avoiding the performance pitfalls of offset‑based pagination.
Prerequisites
- FaunaDB account with a database and an API key that has read permissions for the target collection or index.
- FaunaDB client library installed (Node.js example:
npm install faunadb). - Knowledge of the collection or index you want to paginate. Cursors are index‑specific.
Procedure
- Set up the client:
const faunadb = require('faunadb'); const q = faunadb.query; const client = new faunadb.Client({ secret: 'YOUR_FAUNADB_SECRET' }); - Define the pagination parameters:
limit– number of documents per page.after– optional cursor from the previous page.
- Make the first query (no
afterfor the first page):async function fetchPage(limit, after = undefined) { const payload = { collection: 'Posts', // or an index name limit: limit, after: after }; const result = await client.query(q.paginate(q.ref(q.collection('Posts')), payload)); return result; } fetchPage(5).then(console.log).catch(console.error); - Handle the response:
- Data appears in
result.data– an array of reference IDs. - The cursor for the next page is in
result.after. Store it for the subsequent request.
- Data appears in
- Request the next page using the stored cursor:
fetchPage(5, result.after).then(console.log).catch(console.error);
Expected Checks
- Each page returns the exact number of documents specified by
limit(unless the remaining set is smaller). - Document order is consistent across pages – verify by comparing the last document ID of page 1 with the first of page 2.
- The
aftercursor is non‑empty after the first page and becomesundefinedwhen the last page is reached.
Recovery Options
- If the
aftercursor is invalid (e.g., due to index changes), the query will return an error. In that case, start a new pagination sequence from the beginning. - To avoid stale cursors, include a timestamp or version field in the index and re‑index if data changes significantly between requests.
Limitations and Practical Verification
- Offset‑style
skipis not supported; attempting to emulate it withskipcan cause linear performance degradation. - Cursors are only valid for the index used in the query. A cursor from
Postscannot paginateUsers. - Because cursors are opaque strings, you cannot modify them. Always store the cursor exactly as returned.
To verify the implementation, create a test collection with more than 10 documents, run the first query with limit:5, capture the after cursor, run the second query with that cursor, and confirm that the two result sets contain distinct, non‑overlapping documents. Summing the lengths of both arrays should equal the total document count in the collection.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.