The Point-in-Time (PIT) API provides a lightweight, frozen view of your data at a specific moment. It replaced scroll as the recommended method for deep pagination starting in Elasticsearch 7.10. Unlike scroll, which ties a search context to a single query, a PIT is an independent resource you can use across multiple search requests with different queries, sorts, and aggregations - all against the same consistent snapshot.
When you open a PIT, Elasticsearch prevents segment merges from removing segments that the PIT references. Deleted or updated documents remain tracked so the PIT can determine whether each document was live at creation time. That snapshot consistency is the core value, but it comes with resource costs you need to manage.
Creating and Using a PIT
Open a PIT with a POST request to the target index:
POST /my-index/_pit?keep_alive=5m
The response returns an id field - an opaque string you pass into subsequent search requests. The keep_alive parameter sets the initial time-to-live. It does not need to cover the entire pagination session. Each subsequent search request can extend the keep-alive window:
POST /_search
{
"pit": {
"id": "your_pit_id_here",
"keep_alive": "5m"
},
"sort": [{"@timestamp": "desc"}, {"_shard_doc": "asc"}],
"search_after": [1234567890, 42],
"size": 100
}
Each search response returns an updated PIT ID. Always use the most recently returned ID for the next request. The _shard_doc tiebreaker sort is implicit when using PIT and provides a unique sort value per document, which search_after requires for deterministic pagination.
Do not specify an index in the search body when using PIT - the PIT already carries the target index information. Including both produces an error.
Common Errors
The most frequent PIT error is search_phase_execution_exception caused by an expired or invalid PIT ID. This happens when the keep_alive window elapses between requests. The underlying cause is search_context_missing_exception with the message "No search context found for id [N]". The fix: open a new PIT and restart pagination. You cannot resume from where you left off with an expired PIT.
A NoShardAvailableActionException appears when a PIT references shards that have since become unavailable - after a node restart or shard relocation. The PIT recorded which shards held data at creation time, and if those shards disappear, searches against that PIT report shard failures. Create a fresh PIT so it binds to the current shard allocation.
The "too many open contexts" error occurs when a node exceeds its limit on concurrent search contexts. Both PITs and scrolls share the same context pool, controlled by search.max_open_scroll_context (default: 500 per node). Monitor open contexts with GET /_nodes/stats/indices/search and check the open_contexts field. If it approaches 500, your application has a leak or needs architectural changes - batching PIT creation, reducing concurrency, or increasing the limit after evaluating memory headroom.
Resource Management
Every open PIT holds references to Lucene segments, preventing cleanup during merges. This causes increased disk usage from retained segments, higher file handle consumption, and additional heap usage for tracking per-document liveness in indices with ongoing updates or deletes.
The heap pressure is particularly relevant for indices with high update rates. Each deleted or updated document within a PIT-referenced segment requires bookkeeping. On clusters with hundreds of open PITs against frequently-updated indices, this can push nodes toward circuit breaker thresholds.
Set keep_alive to the shortest practical duration. Use 1-2 minutes for interactive pagination where the next page request arrives within seconds. For batch processing, 5 minutes works if each page is processed quickly. Avoid setting keep_alive to hours - you hold cluster resources the entire time.
PIT vs Scroll Comparison
Scroll is deprecated for deep pagination. The Elasticsearch documentation recommends search_after with PIT as the replacement.
Scroll binds to a single query at creation time. You cannot change the query, sort, or aggregation between scroll requests. PIT decouples the data snapshot from any specific query, so you can run different searches against the same frozen view. Scroll contexts are bound to the coordinating node that initiated the search - if that node goes down, the scroll is lost. PIT IDs are cluster-wide and can be used from any coordinating node.
Performance-wise, search_after with PIT avoids the deep pagination cost of scroll. Scroll internally tracks a global position and must skip past all previous results on each request. search_after uses sort values to jump directly to the right position, making page 1000 as fast as page 1.
Closing PITs Explicitly
PITs are automatically closed when keep_alive expires, but close them explicitly when pagination completes:
DELETE /_pit
{
"id": "your_pit_id_here"
}
This immediately frees associated segments and file handles rather than waiting for the timeout. In application code, wrap PIT usage in a try/finally block or equivalent cleanup pattern. If your process crashes mid-pagination, the PIT will still expire on its own - but relying on that for normal operation wastes resources.
You can close all open PITs with DELETE /_pit?all=true, though this is a blunt instrument best reserved for operational emergencies. It will interrupt any other clients currently paginating through their own PITs.