Bird
Raised Fist0
Firebasecloud~10 mins

Cursor-based pagination (startAfter, endBefore) in Firebase - Step-by-Step Execution

Choose your learning style10 modes available
Process Flow - Cursor-based pagination (startAfter, endBefore)
Start Query
↓
Set Cursor: startAfter or endBefore
↓
Fetch limited items
↓
Return page of results
↓
User requests next/prev page
↓
Update cursor with last/first item
↩Back to Fetch limited items
The query starts with a cursor (startAfter or endBefore) to fetch a limited page of results. The cursor updates with each page to navigate forward or backward.
Execution Sample
Firebase
query = collection.orderBy('timestamp').startAfter(lastDoc).limit(3)
results = query.get()
lastDoc = results[-1]
Fetch 3 items after the last document's timestamp to get the next page.
Process Table
StepActionCursor UsedDocuments FetchedCursor Updated
1Initial query without cursorNoneDoc1, Doc2, Doc3Cursor set to Doc3
2Next page query with startAfter Doc3startAfter Doc3Doc4, Doc5, Doc6Cursor set to Doc6
3Next page query with startAfter Doc6startAfter Doc6Doc7, Doc8Cursor set to Doc8
4Next page query with startAfter Doc8startAfter Doc8No documentsCursor unchanged
5User requests previous page with endBefore Doc4endBefore Doc4Doc1, Doc2, Doc3Cursor set to Doc1
6User requests previous page with endBefore Doc1endBefore Doc1No documentsCursor unchanged
💡 No more documents to fetch; pagination ends.
Status Tracker
VariableStartAfter Step 1After Step 2After Step 3After Step 4After Step 5After Step 6
cursorNoneDoc3Doc6Doc8Doc8Doc1Doc1
fetched_docs[][Doc1, Doc2, Doc3][Doc4, Doc5, Doc6][Doc7, Doc8][][Doc1, Doc2, Doc3][]
Key Moments - 3 Insights
Why does the cursor update to the last document after fetching a page?
Because the cursor marks the position to start the next query after the last fetched document, as shown in steps 1-3 in the execution_table.
What happens when there are no more documents after the cursor?
The query returns no documents and the cursor does not update, as seen in step 4 and step 6 in the execution_table.
How does endBefore help in fetching previous pages?
endBefore sets the cursor before a document to fetch documents before it, enabling backward pagination, demonstrated in step 5.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the cursor after step 2?
ADoc6
BDoc8
CDoc3
DNone
💡 Hint
Check the 'Cursor Updated' column in row for step 2.
At which step does the query return no documents because there are no more after the cursor?
AStep 3
BStep 4
CStep 5
DStep 6
💡 Hint
Look for 'No documents' in the 'Documents Fetched' column.
If the user wants to go back to the first page, which cursor method is used according to the table?
AstartAfter
Blimit
CendBefore
DorderBy
💡 Hint
See step 5 where previous page is requested.
Concept Snapshot
Cursor-based pagination uses a document snapshot as a cursor.
startAfter fetches documents after the cursor.
endBefore fetches documents before the cursor.
Use limit() to control page size.
Update cursor each page to navigate.
No documents means end of pagination.
Full Transcript
Cursor-based pagination in Firebase uses document snapshots as cursors to fetch pages of data. The startAfter cursor fetches documents after a given document, while endBefore fetches documents before it. Each query uses limit() to control how many documents to fetch per page. After fetching, the cursor updates to the last or first document to enable navigation to next or previous pages. When no documents are returned, it means the end or start of the data is reached. This method is efficient and reliable for paginating large datasets.

Practice

(1/5)
1. What does the startAfter method do in Firebase cursor-based pagination?
easy
A. It loads all documents from the beginning.
B. It ends the query before a specific document snapshot.
C. It deletes documents after a specific snapshot.
D. It starts loading documents after a specific document snapshot.

Solution

  1. Step 1: Understand the purpose of startAfter

    startAfter tells Firebase to begin loading documents after the given document snapshot, skipping that snapshot itself.
  2. Step 2: Compare with other cursor methods

    endBefore stops before a snapshot, but startAfter moves forward after it.
  3. Final Answer:

    It starts loading documents after a specific document snapshot. -> Option D
  4. Quick Check:

    startAfter = start after snapshot [OK]
Hint: Remember: startAfter skips the given document and moves forward [OK]
Common Mistakes:
  • Confusing startAfter with endBefore
  • Thinking startAfter includes the given document
  • Assuming startAfter loads all documents from start
2. Which of the following is the correct syntax to start a query after a document snapshot named lastDoc in Firebase?
easy
A. query.startAfter(lastDoc)
B. query.endAfter(lastDoc)
C. query.startBefore(lastDoc)
D. query.endBefore(lastDoc)

Solution

  1. Step 1: Recall Firebase query cursor methods

    The correct method to start after a document is startAfter().
  2. Step 2: Match method with snapshot variable

    Using startAfter(lastDoc) correctly applies the cursor after the lastDoc snapshot.
  3. Final Answer:

    query.startAfter(lastDoc) -> Option A
  4. Quick Check:

    Correct method is startAfter() [OK]
Hint: Use startAfter(snapshot) to move forward in pagination [OK]
Common Mistakes:
  • Using non-existent methods like endAfter or startBefore
  • Mixing up startAfter and endBefore
  • Forgetting to pass the snapshot as argument
3. Given the following code snippet, what documents will be returned?
const firstPage = await collection.orderBy('name').limit(3).get();
const nextPage = await collection.orderBy('name').startAfter(firstPage.docs[2]).limit(3).get();
medium
A. Documents 1 to 3 on firstPage, documents 4 to 6 on nextPage
B. Documents 1 to 3 on firstPage, documents 3 to 5 on nextPage
C. Documents 1 to 2 on firstPage, documents 3 to 5 on nextPage
D. Documents 1 to 3 on firstPage, documents 1 to 3 again on nextPage

Solution

  1. Step 1: Understand firstPage query

    The first query orders by 'name' and limits to 3 documents, so it returns documents 1, 2, and 3.
  2. Step 2: Understand nextPage query with startAfter

    Using startAfter(firstPage.docs[2]) starts after the third document, so nextPage returns documents 4, 5, and 6.
  3. Final Answer:

    Documents 1 to 3 on firstPage, documents 4 to 6 on nextPage -> Option A
  4. Quick Check:

    startAfter skips last doc, nextPage continues [OK]
Hint: startAfter skips last doc, next page continues from next doc [OK]
Common Mistakes:
  • Assuming startAfter includes the last document again
  • Confusing document indexes (0-based vs 1-based)
  • Not ordering consistently before pagination
4. You wrote this code but it throws an error:
const prevPage = await collection.orderBy('date').endBefore(lastDoc).limitToLast(3).get();
What is the likely cause?
medium
A. Using limitToLast without endBefore causes error
B. You must use startAfter instead of endBefore
C. The lastDoc snapshot is not from the same query order
D. Firebase does not support endBefore with limitToLast

Solution

  1. Step 1: Check cursor snapshot origin

    The snapshot lastDoc must come from a query with the same ordering and filters.
  2. Step 2: Understand error cause

    If lastDoc is from a different query or unordered, Firebase throws an error.
  3. Final Answer:

    The lastDoc snapshot is not from the same query order -> Option C
  4. Quick Check:

    Cursor snapshot must match query order [OK]
Hint: Cursor snapshot must come from same ordered query [OK]
Common Mistakes:
  • Using snapshot from different query or order
  • Mixing startAfter and endBefore incorrectly
  • Ignoring need for consistent ordering
5. You want to implement backward pagination to load previous 5 documents before a known document snapshot currentDoc. Which Firebase query correctly achieves this?
hard
A. collection.orderBy('timestamp').startAfter(currentDoc).limit(5)
B. collection.orderBy('timestamp').endBefore(currentDoc).limitToLast(5)
C. collection.orderBy('timestamp').startAt(currentDoc).limit(5)
D. collection.orderBy('timestamp').endAt(currentDoc).limitToLast(5)

Solution

  1. Step 1: Understand backward pagination

    To load documents before currentDoc, use endBefore(currentDoc).
  2. Step 2: Use limitToLast for correct order

    Using limitToLast(5) returns the last 5 documents before currentDoc in correct order.
  3. Final Answer:

    collection.orderBy('timestamp').endBefore(currentDoc).limitToLast(5) -> Option B
  4. Quick Check:

    Backward pagination uses endBefore + limitToLast [OK]
Hint: Backward pagination = endBefore + limitToLast [OK]
Common Mistakes:
  • Using startAfter for backward pagination
  • Using limit instead of limitToLast when going backward
  • Confusing endBefore with endAt
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard