## TL;DR

Page with search_after using the sort values of the last hit from the previous page. OpenSearch requires this for deep pagination because offset paging past its result window is rejected. Walk by sort position and the requirement is satisfied.

```text
opensearch error: search_after is required for deep pagination
```

## Steps

1. Confirm your code paginates with from and size into deep offsets. Expected: you find the offset-based loop that OpenSearch rejects.

2. Add a deterministic sort to the query, ending with a unique field as tiebreaker so no two hits share a sort position. Expected: every hit has a unique, stable sort key.

3. Request the first page with your chosen size and no search_after. Expected: you get page one plus the sort values on each hit.

4. For each next page, set search_after to the sort values of the last hit of the previous page. Expected: pages advance through the result set without offsets.

5. Re-run the full walk to the depth you need. Expected: OpenSearch returns every page with no search_after error.

## Use this when

- OpenSearch returns an error saying search_after is required for deep pagination.
- A generated client pages with from and size through a large result set.
- You need reliable ordering across pages while the index updates.

## Not for this skill when

- The query is malformed (that fails on the first page too).
- The cluster is red or out of resources (fix cluster health first).
- You only need shallow pages where from and size are still allowed.

## Variant phrasings

- OpenSearch deep pagination search_after required
- OpenSearch offset pagination not allowed deep
- OpenSearch paginate past 10000 results

## Why it happens

OpenSearch, like Elasticsearch, refuses expensive deep-offset pagination and requires search_after instead: paging by the sort position of the last seen hit rather than by a row number. Generated clients default to from and size because that pattern works on small result sets, and it breaks the moment the walk goes deep.

## Edge cases

- The sort must be identical on every page request; even reordering the sort fields breaks the sequence.
- Without a unique tiebreaker, hits with equal sort values can be skipped or duplicated across page boundaries.
- If the index updates mid-walk, results can shift; for a stable snapshot use a point-in-time reader underneath the search_after walk.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_Pog7dfxf8Uad60MdqbNC3A
