Elasticsearch Pagination: Handling Deep Result Sets
Fast recall
Quick revision
Core answer
Whether you understand why from/size pagination degrades at depth and can describe the search_after pattern for efficient stateless pagination.
Using from/size for unbounded pagination (fetching page 1000 of results), which causes Elasticsearch to retrieve and discard enormous numbers of documents across all shards.
Explain the scatter-gather cost of deep from/size pagination -- each shard returns (from + size) results to the coordinating node, which must sort and discard from of them, so page 1000 of 10 results requires each shard to return 10,010 hits.
Interview-ready guide
Interview answer
Elasticsearch supports three pagination approaches, and the choice depends on how deep you need to paginate — each has trade-offs that make one clearly better for different use cases.
from/size — simple but breaks at depth
from: 0, size: 10returns the first page;from: 990, size: 10returns page 100 — but to serve page 100, Elasticsearch must retrieve the top 1,000 results from every shard, merge them, and discard 990 — which means a request for page 1,000 with size 10 moves 10,000 results from each shard, even if there are 20 shards- The default
index.max_result_windowis 10,000 — requests beyond that fail; this is not a bug, it's protecting against the memory and bandwidth cost of deep pagination
search_after — cursor-based, forward only
search_afteruses the sort values of the last document in the previous page as a cursor —"search_after": [1704067200, "doc-id-xyz"]returns results after that point in the sort order- This is stateless — no need to track a scroll context; suitable for real-time search results where users page forward; the trade-off is that it's forward-only (no jumping to page 50) and the sort must be deterministic (include a unique tiebreaker like
_id)
Scroll API — for bulk export
POST /index/_search?scroll=2mopens a point-in-time snapshot and returns ascroll_id; subsequent requests with that scroll_id return the next batch, always from the same snapshot- Scroll is designed for bulk data export — exporting all documents, feeding an ETL pipeline — not for user-facing pagination; scroll contexts consume memory on the cluster for the duration of the scroll
- Point-in-time (PIT) with
search_afteris the modern replacement for Scroll:POST /index/_pit?keep_alive=5mopens a snapshot; subsequent searches with the PIT ID andsearch_afterpage through it without maintaining per-shard state
Elasticsearch Pagination: Handling Deep Result Sets
Direct Answer
Elasticsearch supports three pagination mechanisms. The from/size approach is simple but becomes prohibitively expensive beyond 10,000 results because every shard must sort and return from + size results. The search_after approach uses a sort value cursor for efficient deep pagination without skipping results. The scroll API was designed for bulk data export but is deprecated for user-facing pagination -- search_after is the recommended replacement.
Common Mistakes & Pitfalls
Using from/size for unbounded pagination (fetching page 1000 of results), which causes Elasticsearch to retrieve and discard enormous numbers of documents across all shards.
Check your understanding
Answer these without looking back at the article.
- What is a Point In Time (PIT) context in Elasticsearch and when do you need it?
- What are the trade-offs of search_after versus from/size for user-facing search UIs?
- How do you implement a 'jump to page' feature when using search_after?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.