# Pagination: from/size, search_after and Point in Time — Elasticsearch

Source: https://www.skillbyai.com/en/elasticsearch/s-paging

> Page safely through results.

## Why deep pages are expensive

`from` and `size` are fine for the first few pages, but every shard must collect `from + size` hits and the coordinating node must sort them all, so cost grows with depth. Elasticsearch limits `from + size` to `index.max_result_window` (default 10,000). For deep or "load more" pagination, use **search_after**: sort on fields with a unique tiebreaker and pass the sort values of the last hit to get the next page. To keep pages consistent while data changes, open a **point in time (PIT)**, which freezes a view of the index; search with the PIT id (no index in the path) and keep it alive with `keep_alive`. The scroll API is no longer recommended for deep pagination; PIT plus search_after replaces it.

## Beyond the first page of results

Real search UIs need stable pagination, highlighted snippets, suggestions while typing and, increasingly, semantic matching.

![Three ideas: pagination, highlighting and autocomplete, vector search.](assets/figures/elasticsearch/section-6-map.svg) — Figure 6.1 — Query, results page, highlights and suggestions.

## Point in time with search_after

Kibana Dev Tools console syntax; send the same requests with curl or a client library.

```http
POST /products/_pit?keep_alive=1m
# -> { "id": "<pit-id>" }

GET /_search
{
  "size": 50,
  "query": { "match": { "name": "jacket" } },
  "pit": { "id": "<pit-id>", "keep_alive": "1m" },
  "sort": [ { "price": "asc" }, { "_shard_doc": "asc" } ]
}

# next page: pass the "sort" array from the last hit of the previous page
GET /_search
{
  "size": 50,
  "query": { "match": { "name": "jacket" } },
  "pit": { "id": "<pit-id>", "keep_alive": "1m" },
  "sort": [ { "price": "asc" }, { "_shard_doc": "asc" } ],
  "search_after": [ 79.9, 1234 ]
}

DELETE /_pit
{ "id": "<pit-id>" }
```

## Users rarely need page 500

Cap UI pagination (for example 50 pages) and offer better filters instead. Use PIT and search_after for exports and background jobs that genuinely walk everything.

**Quiz:** What is the recommended way to page deeply through results?

- [ ] Raising max_result_window to millions
- [ ] from and size with a large from
- [x] search_after with a point in time
- [ ] One query per shard

*Answer:* search_after with a point in time. It avoids collecting from + size hits on every shard.
