From/size vs search_after vs scroll in Elasticsearch: Key Differences and Usage
from/size is simple pagination but inefficient for deep pages, search_after is a performant cursor-based pagination for sorted results, and scroll is designed for retrieving large datasets efficiently in batches without real-time relevance. Choose based on data size and use case.Quick Comparison
This table summarizes the main differences between from/size, search_after, and scroll in Elasticsearch.
| Feature | from/size | search_after | scroll |
|---|---|---|---|
| Use case | Simple pagination for small offsets | Efficient deep pagination with sorting | Extracting large datasets in batches |
| Performance | Slower for large offsets | Fast and efficient | Optimized for large data retrieval |
| Statefulness | Stateless | Stateless | Stateful (keeps context) |
| Sorting requirement | No strict sorting needed | Requires unique sort keys | No strict sorting needed |
| Data freshness | Real-time | Real-time | Snapshot at scroll start |
| Complexity | Simple to use | Moderate complexity | More complex, needs scroll context |
Key Differences
from/size is the simplest way to paginate results by skipping from records and returning size records. However, it becomes slow and resource-heavy for large from values because Elasticsearch must skip many records internally.
search_after uses a cursor-like approach by passing the last sort values from the previous page to fetch the next page. It requires a unique and consistent sort order but is much faster and more efficient for deep pagination since it avoids skipping.
scroll is designed for extracting large volumes of data in batches. It creates a snapshot of the data at the start and keeps a context open on the server. This method is stateful and not suitable for real-time user pagination but excellent for exporting or reindexing large datasets.
Code Comparison
Example of paginating with from/size to get the second page of 10 results sorted by timestamp:
{
"query": { "match_all": {} },
"sort": [ { "timestamp": "asc" } ],
"from": 10,
"size": 10
}search_after Equivalent
Example of paginating with search_after using the last hit's sort values ["2023-01-01T12:00:00", "abc123"]:
{
"query": { "match_all": {} },
"sort": [ { "timestamp": "asc" }, { "_id": "asc" } ],
"size": 10,
"search_after": ["2023-01-01T12:00:00", "abc123"]
}When to Use Which
Choose from/size for simple, shallow pagination with small offsets where performance impact is minimal.
Choose search_after for efficient deep pagination on sorted data when you need fast response times and consistent ordering.
Choose scroll when you need to retrieve large datasets in bulk, such as for data export or reindexing, and real-time freshness is not critical.
Key Takeaways
from/size is easy but slow for deep pages.search_after is efficient cursor-based pagination requiring unique sorting.scroll is best for large bulk data retrieval, not real-time pagination.search_after for deep pagination with sorting, from/size for simple cases.scroll keeps server state and snapshots data at query start.