What Is Async Search in Elasticsearch?
A complete, beginner-friendly guide to running slow, heavy searches in the background: how you submit them, watch their progress, read partial results, fetch the final answer later, and clean up after yourself.
Imagine you order a huge, freshly baked pizza for a class party. You could stand at the counter, staring at the oven for twenty minutes, unable to do anything else, and hoping nobody closes the shop before it is ready. Or the shop could hand you a numbered ticket, let you sit down, and tell you, “Come back whenever you like, show this ticket, and we will tell you whether it is done. In the meantime, here is a first slice so you can taste how it is going.” The second way is far more comfortable, and it is exactly the idea behind async search.
Most Elasticsearch searches finish in a few milliseconds, so waiting at the counter is fine. But some searches, such as one that crunches months of logs across hundreds of shards, or one that reaches into slow, cheap storage for old data, can take many seconds or even minutes. For those, holding a connection open and hoping for the best is fragile and unfriendly. In this tutorial we start from the very beginning and build up to a full understanding of async search: what problem it solves, how its four operations work, what the fields in its responses mean, what it costs your cluster, how to secure and monitor it, and how to avoid the classic mistakes.
1The Big Picture: How a Normal Search Works
Before we can appreciate the background version, we need to understand what happens when you run an ordinary search.
Clusters, shards and the search request
Elasticsearch stores documents in indices, and each index is divided into shards, which are smaller pieces that can live on different machines called nodes. When you send a search request, one node receives it and becomes the coordinating node for that request. It works out which shards must be asked, sends the query to each of them, and waits for their answers. Each shard searches its own data and returns its best results. The coordinating node then merges all these partial answers into one combined result and sends it back to you.
This two-step dance, ask every shard and then merge, is often called scatter and gather. The important thing for us is the waiting. The coordinating node cannot answer you until every shard has replied, or until the request runs out of time. If one shard is slow, everybody waits for that shard. The client, meanwhile, keeps its connection open the whole time, holding a line until the answer arrives.
Think of a teacher asking each of thirty students to count the red marbles in their own bag and report back. The teacher writes down each number and adds them up at the end. If twenty-nine students answer in five seconds but one student has a giant bag and needs two minutes, the teacher cannot announce the final total until that last student finishes.
sequenceDiagram
participant C as Client
participant N as Coordinating node
participant S1 as Shard 1
participant S2 as Shard 2
participant S3 as Shard 3
C->>N: Search request (connection held open)
N->>S1: Run query
N->>S2: Run query
N->>S3: Run query
S1-->>N: Results
S2-->>N: Results
S3-->>N: Results (slowest)
N-->>C: Merged final result
Where the time goes
The time a search takes depends on several things: how many shards are involved, how much data each holds, how complicated the query is, whether aggregations must be computed, and how fast the underlying storage is. A simple lookup on a small index is instantaneous. A wide aggregation over a year of data spread across hundreds of shards is a different story, and the work adds up quickly.
Coordinating node
The node that receives a search request, fans it out to shards, and merges the answers.
Shard
A slice of an index that holds part of the data and can be searched on its own.
Aggregation
A calculation over many documents, such as counts per category or averages per day.
Reduce phase
The step in which the coordinating node merges shard-level results into one combined result.
Timeout
A limit on how long something is allowed to take before it is cut short or abandoned.
Search task
The running unit of work that Elasticsearch tracks internally for each search.
Even in a normal search, Elasticsearch can give you a partial answer if you set a search timeout, returning whatever the shards produced in time and marking the response as timed out. Async search takes the idea much further, as we will see.
2The Problem: Why Slow Searches Hurt
A slow search is not just an inconvenience. It creates a chain of small problems that all trace back to one long wait.
Long-held connections are fragile
When a client waits for a long search, a connection stays open between the client and Elasticsearch, and often through several other machines in between, such as load balancers, reverse proxies and API gateways. Each of these middle machines usually has its own idle timeout, commonly somewhere between thirty and sixty seconds. If your search takes longer, one of them may cut the connection, and you receive a gateway error even though Elasticsearch is still happily working on your request.
Mobile networks, office Wi-Fi and laptops that go to sleep add more ways for a connection to break. When it breaks, the client has no answer and no way to get one, even if the cluster finishes the work moments later. All that effort is wasted, and the user must start again, making the cluster do the same heavy work a second time.
The user experience suffers
People are patient with a progress bar and impatient with a frozen screen. A dashboard that shows nothing for forty seconds and then either loads or errors out feels broken. A dashboard that shows a bar creeping forward, along with early numbers that keep improving, feels alive. The difference is not the total time; it is whether the user is kept informed.
Compare two delivery apps. One shows a blank screen after you order and gives you your food, or an error, thirty minutes later. The other shows “order received, cooking, on the way” with a map. The food takes the same time in both cases, but the second app keeps you calm, and if you close the app and reopen it, your order is still there.
Slow storage and huge data make it worse
Modern deployments often keep recent data on fast machines and older data on slower, cheaper storage, sometimes even on object storage in the cloud. Searching such data can take much longer, because bytes must be fetched from far away before they can be examined. Users still want to search it, since investigations often need to look back months or years, but they cannot reasonably be asked to wait on an open connection for minutes.
Security investigations
An analyst hunts through half a year of network logs for a suspicious address. The search is inevitably heavy, and the analyst wants early hints while it runs.
Business reporting
A finance dashboard computes totals over several years of transactions. It runs rarely but is expensive, and the person who launched it may switch to another task while it runs.
Cross-cluster searches
A search spans clusters in several regions, and the slowest region dictates the total time, with network delays in the mix.
Some teams respond to timeouts by simply raising every timeout in the chain to five or ten minutes. This helps only a little, keeps precious connections busy, and does nothing for the user who is staring at a blank screen. A better answer is to change the interaction pattern itself.
3What Is Async Search?
Async search lets you start a search, stop waiting for it, and come back later for the answer.
A precise definition
Async search is a feature of Elasticsearch that lets a client submit a search request and get control back immediately, without holding the connection open until the search finishes. The search keeps running inside the cluster. Elasticsearch gives the client an identifier for the running search, and the client can use that identifier to check progress, read partial results while the search is still running, fetch the final result once it completes, and finally delete the search when it is no longer needed.
The word “async” is short for asynchronous, which means “not happening at the same moment.” In a normal search, asking and answering happen in one continuous exchange. In async search, asking and answering are separated in time. You ask now, and you collect the answer whenever it suits you, as long as you do it before the stored result expires.
Async search is like leaving a shirt at a dry cleaner. You hand it over, get a numbered slip, and go about your day. You can phone to ask “is it ready yet?” using the slip number. When it is ready, you collect it. If you forget to collect it for a long time, the shop eventually throws the slip away and the shirt is gone.
The three big ideas
Detach
The search no longer depends on your open connection. It runs on its own inside the cluster until it finishes or is cancelled.
Observe
You can look at progress and even partial results while the search is still running, which lets a user interface feel alive.
Retrieve later
The final result can be stored for a chosen period and fetched using an identifier, even from a different connection.
What async search is not
It is very important to understand that async search does not make a search faster. The same shards do the same work, using the same amount of processing time and memory. What changes is how the client and the cluster communicate about that work. It is a change in the conversation, not a shortcut through the data. If a search takes two minutes normally, it will take about two minutes as an async search too, but you will not have to stand still for those two minutes.
graph LR
A["Client submits search"] --> B["Cluster starts work and returns an id"]
B --> C["Client does other things"]
B --> D["Search keeps running in the cluster"]
C --> E["Client checks progress with the id"]
D --> F["Result stored for a limited time"]
E --> G["Client fetches result when ready"]
F --> G
Async search gives you three superpowers: you can walk away, you can peek at early results, and you can pick up the answer later. It gives you no speed-up, and it does not remove the cost of heavy queries.
4The Four Operations of the Async Search API
The whole feature is built from four simple operations. Learn these and you understand the entire API.
Submit, get, status and delete
The async search API is a small family of operations. Submitting starts a search and looks very much like the ordinary search request, sent to an async search endpoint under the target index, and it accepts the same kind of query body. Getting fetches the current state and results of a previously submitted search by its identifier. Status returns only the lightweight state of the search, without the results. Deleting removes the search, cancelling it if it is still running, and discarding any stored result.
| Operation | Endpoint idea | What it does | When you use it |
|---|---|---|---|
| Submit | POST to the async search endpoint, optionally under an index name | Starts the search and returns early with an id if still running | Once, to begin |
| Get | GET on the async search endpoint with an id | Returns current state, partial or final results, and can extend the lifetime | To read progress or the final answer |
| Status | GET on the async search status endpoint with an id | Returns running state and shard progress, but no results | To poll cheaply |
| Delete | DELETE on the async search endpoint with an id | Cancels a running search and removes any stored result | When finished or abandoned |
Back to the dry cleaner: submit is handing in the shirt, get is collecting it, status is phoning to ask whether it is ready, and delete is telling the shop “I no longer need this, you can throw it away.”
Why a separate status operation?
The get operation returns the whole response, which may contain large lists of hits and complicated aggregation results. If you just want to know whether the search has finished, fetching all that is wasteful. The status operation returns only a small summary: whether the search is still running, whether the result is partial, when it started, when it will expire, how many shards have finished, and, once complete, a completion code. It is meant for polling, the polite repeated checking that a client does while waiting.
The identifier
The submit operation returns an identifier, a long, opaque string. You should treat it as a handle that you pass back unchanged, without trying to read anything into its contents. The identifier is only returned if the search is still running when the submit call returns, or if you asked Elasticsearch to keep the result even when the search completes quickly. If the search finishes fast and you did not ask for storage, there is nothing left to point to, and no identifier is returned at all.
The id
A token used to refer to a running or stored search. Keep it safe and pass it back exactly as received.
The expiry time
The moment after which Elasticsearch will delete the search and its result, reported in every response.
The running flag
A simple true or false telling you whether work is still in progress inside the cluster.
The partial flag
Tells you whether the results you are looking at are incomplete or final.
Many other Elasticsearch features that can run long, such as event query language searches and SQL queries, have their own asynchronous variants that follow the same submit, check, fetch and delete pattern, so learning it once pays off several times.
5The Life of an Async Search, Step by Step
Let us follow a single async search from birth to cleanup so that every moving part has a place in your mind.
The client submits
The client sends the query to the submit endpoint, along with a small wait time, saying “give me the answer if you can within this time, otherwise hand me a ticket.”
The cluster starts the search
The coordinating node creates a search task, contacts the relevant shards and begins collecting their answers exactly as in a normal search.
The wait window closes
If the search finishes inside the wait window, the complete result is returned straight away. If not, Elasticsearch returns whatever it has so far, with a running flag set and an identifier.
Work continues in the background
The connection is now free. As shards report in, the coordinating node periodically merges batches of shard results, keeping an up-to-date partial result available.
The client checks in
Using the identifier, the client polls the status endpoint, or asks for the current result, and shows progress or early numbers to the user.
The search completes
Once every shard has answered, or failed, the final merge happens. The complete result is stored so that it can be fetched, at least until its expiry time.
The client fetches and cleans up
The client retrieves the final result and then deletes the search. If it forgets, Elasticsearch removes the search automatically after the expiry time.
sequenceDiagram
participant C as Client
participant N as Coordinating node
participant S as Shards
C->>N: Submit search (wait up to a short time)
N->>S: Run query on all shards
Note over C,N: Wait window ends, search still running
N-->>C: Id, running flag, partial result
S-->>N: Shard results arrive over time
C->>N: Status check with id
N-->>C: Still running, 40 of 100 shards done
C->>N: Status check with id
N-->>C: Completed
C->>N: Get result with id
N-->>C: Final result
C->>N: Delete search with id
N-->>C: Acknowledged
If the search completes within the wait window, and you did not ask to keep the result, everything happens in one round trip, just like a normal search. Async search does not force you into the long path for quick queries.
6The Three Key Settings on Submit
Three settings decide almost everything about how an async search behaves. Get comfortable with them.
Wait for completion timeout
This setting says how long the submit call should wait for the search to finish before returning. Its default is a very short time, about one second. If the search finishes within that time, you get the full result immediately. If not, the call returns anyway, with an identifier and whatever partial result is available. Raising it makes fast-ish searches behave like ordinary ones, while lowering it makes the call hand back a ticket almost instantly.
Keep on completion
By default, Elasticsearch stores a search result only if the search is still running when the submit call returns. If the search finishes inside the wait window, the result is returned directly and nothing is stored. Setting keep on completion to true changes this: the result is stored even when the search finishes within the window, so that it can be fetched again later using its identifier. This is useful when a user might reload a page and expect to see the same result.
Keep alive
This is the lifetime of the stored search. After the keep alive period passes, Elasticsearch will delete the search and its result. The default is several days, which is generous. You can shorten it to save space, or extend it when you fetch a result, for example if a user is still looking at a report. Think of it as the number of days the dry cleaner promises to keep your shirt on the rack.
| Situation | Wait window | Keep on completion | What you get |
|---|---|---|---|
| Search finishes quickly | Not exceeded | False (default) | Full result immediately, nothing stored, no id |
| Search finishes quickly | Not exceeded | True | Full result immediately, plus a stored copy and an id |
| Search is slow | Exceeded | Either | Partial result now, an id, and the final result stored on completion |
| Search fails quickly | Not exceeded | False (default) | Error returned directly |
| Search is slow and later fails | Exceeded | Either | Id returned; failure information is available when you fetch |
The wait window is how long the shop clerk will let you stand at the counter before handing you a slip. Keep on completion is you asking, “Even if it is done at once, please keep a copy in case I lose mine.” Keep alive is how long the shop promises to hold your order.
Leaving keep alive at its long default for thousands of searches that nobody will ever fetch again quietly fills a system index with stored results. Set the lifetime to match how long the answer is truly useful, and delete results when you are done.
7Reading the Response: Every Field Explained
An async search response is a normal search response wrapped in a small envelope. Understanding the envelope is the key.
The envelope fields
id
The identifier of the search. Present when the search is still running or has been stored.
is_running
True while shards are still being searched, false once the search has finished, failed or been cancelled.
is_partial
While running, always true. After completion, it tells you whether the search failed or was successful on all shards.
start_time_in_millis
When the search started, as a timestamp in milliseconds since the beginning of 1970.
expiration_time_in_millis
When the search and its result will be automatically deleted, unless the lifetime is extended.
response
The familiar search response body, with hits, aggregations and shard information, possibly partial.
The shard progress counters
Inside the response body, a section about shards reports the total number of shards involved, how many have successfully answered, how many were skipped because they could not possibly match, and how many failed. While the search runs, the successful count climbs toward the total. This gives a natural progress measure: forty successful shards out of a hundred means roughly forty percent of the shards have answered, though it is not a precise percentage of time remaining, because shards differ in size and speed.
Imagine a teacher collecting homework from a hundred students. “Forty handed in” is a helpful progress note. It does not tell you when the last ones will finish, since some students have short assignments and others have long ones, but it does tell you how far along the pile is.
What the partial flag really means
The partial flag is easy to misread. While the search is still running, the flag is always true, because you are looking at an incomplete picture. Once the search has finished, the flag has a second meaning: it is false if the search succeeded on all shards, and true if it failed or some shards could not be searched. This means a finished search with the partial flag set to true is a warning sign. It tells you that the results may not represent all your data, and you should look at the shard failure information before trusting them.
| is_running | is_partial | Meaning |
|---|---|---|
| true | true | Still working. What you see is a snapshot in progress |
| false | false | Finished and succeeded on all shards. Safe to treat as final |
| false | true | Finished, but failed or missed some shards. Inspect failures before trusting |
A user interface that shows numbers as final whenever the running flag turns false, without looking at the partial flag and the shard failure counts, can present incomplete data as if it were complete. In reports and audits, that can be a serious error.
8Partial Results and Progressive Aggregations
One of the nicest features of async search is that early answers arrive while the rest is still being computed.
How partial results are built
As shard answers arrive at the coordinating node, they are not merged all at once at the very end. Instead, the coordinating node merges them in batches. The number of shard results merged at a time is controlled by a setting called batched reduce size, with a default of five. Each time a batch is merged, the running combined result is updated, and that updated result is what a client sees when it asks for the current state.
This has a second benefit that has nothing to do with progress bars: merging in batches keeps memory use under control on the coordinating node. Holding hundreds of full shard results at once before merging can consume a lot of memory, whereas merging as you go lets earlier pieces be released.
Imagine adding up a hundred bags of marbles. You could wait for all hundred to arrive and then add them together in a single huge pile, or you could add every five bags as they come in and keep a running total on a piece of paper. The running total is always available, and the table never gets crowded.
graph TD
S1["Shard results 1-5"] --> R1["Partial merge A"]
S2["Shard results 6-10"] --> R2["Partial merge B"]
R1 --> P["Running combined result"]
R2 --> P
S3["More shard results"] --> R3["Partial merge C"]
R3 --> P
P --> V["Visible to the client as a partial response"]
P --> F["Final result once every shard has answered"]
What a user can do with partial results
A dashboard can draw charts from partial aggregations, and let them refine as more shards report in. A search page can display the first hits found while the rest of the shards are still working. An analyst can decide early that a query is on the wrong track and cancel it, saving cluster resources. All of these turn a long blank wait into an active experience.
Progressive charts
A time-series chart appears with rough shapes after a few seconds and sharpens as more shards contribute. Users can spot trends early.
Early cancellation
After seeing the first partial numbers, an analyst realises the filter was wrong and cancels the search, freeing the cluster for other work.
Best-effort answers
In some monitoring uses, a partial answer from most shards is good enough to decide whether something looks alarming, while the exact final number can arrive later.
The honesty problem
Partial results are exactly that: partial. A count computed from thirty percent of the shards is not thirty percent of the final answer in any reliable sense, because data is not evenly spread. Top-ten lists can change entirely as new shards contribute. Averages can shift. Minimums and maximums can jump. A well-designed interface labels early numbers clearly as provisional, for example with a “still loading” indicator, and avoids drawing firm conclusions or triggering actions such as alerts from them.
Never let a script make an important decision, such as raising an incident or generating an invoice, from a partial result. Wait until the search has finished and the partial flag confirms success on all shards.
9Polling with the Status API
Checking on a search should be cheap, polite and predictable. The status operation exists for exactly this.
What the status operation returns
The status response is a compact summary. It includes whether the search is running, whether it is partial, the start and expiry times, the shard progress counters, and, once the search is complete, a completion status code that mirrors the code an ordinary search would have returned, such as success or a failure code. It does not include hits or aggregations, so it is small and quick to produce.
Polling strategies
Polling means asking repeatedly. Done carelessly, it can flood the cluster with pointless requests. Done thoughtfully, it is almost free. The most common good practice is to start with short intervals, since many searches finish soon, and then lengthen the interval gradually the longer the search runs, a technique known as backoff. A pause of one second, then two, then four, up to a modest ceiling such as ten or fifteen seconds, works well for most interfaces.
Submit with a short wait
Wait a second or two for quick wins. If the search finishes, you are done in one call.
Poll the status quickly at first
Check after one second, then two, showing shard progress to the user as a progress bar.
Back off gradually
Lengthen the delay up to a sensible maximum so that long searches do not cause a stream of requests.
Fetch results once, on completion
When the status says the search is finished, fetch the full result a single time and display it.
Stop when the user leaves
If the user closes the page, stop polling and, if the result is no longer needed, delete the search.
Asking “are we there yet?” every ten seconds on a long car ride is annoying. Asking once every few minutes, with a quick look at the map in between, gets you the same information without driving everyone mad. Backoff is the polite way of asking.
Long polling as an alternative
The get operation itself supports a wait time. If you ask for the current result and provide a short wait, Elasticsearch will hold the request for up to that long, returning early if the search completes. This gives you a form of long polling, where each check waits a little inside the cluster instead of returning immediately. It reduces the number of round trips, at the cost of holding a connection briefly, so keep waits short enough to stay within any proxy timeouts.
flowchart TD
A["Submit search"] --> B{"Finished within wait window?"}
B -->|"Yes"| C["Show final result"]
B -->|"No"| D["Receive id and partial result"]
D --> E["Wait, then check status"]
E --> F{"Still running?"}
F -->|"Yes"| G["Increase delay, update progress bar"]
G --> E
F -->|"No"| H{"Partial flag false?"}
H -->|"Yes"| I["Fetch and show final result"]
H -->|"No"| J["Inspect failures and warn the user"]
Add a little random jitter to polling intervals when many clients poll at once. Without it, hundreds of users who started at the same moment will all poll at the same instant, creating small bursts of traffic.
10Where Results Live: Storage, Expiry and Size Limits
Stored results are real data on real disks. They deserve the same care you give to any other data.
A dedicated system index
Elasticsearch keeps the state and results of async searches in a special hidden system index reserved for this purpose. You do not create or manage it directly, and you should not write to it yourself. It is an ordinary index in terms of storage, which means the stored results occupy disk space on the cluster, take part in replication, and are affected by disk watermarks like any other data.
Expiry and clean-up
Every stored search has an expiry time, based on its keep alive period. After that moment, the search is no longer accessible, and a background maintenance task periodically deletes expired entries from the system index. Because clean-up runs periodically, an expired result may linger briefly on disk, but it can no longer be retrieved. You can extend the lifetime by fetching the search and asking for a longer keep alive, and you can shorten its life by deleting it explicitly.
A size limit for each stored response
To protect the cluster, there is a limit on the size of a stored async search response, controlled by a cluster setting with a default of ten megabytes. If a completed search would produce a response larger than the limit, the search is marked as failed instead of storing an enormous result. This is a good reminder that async search is meant for delivering answers, such as summaries and reasonably sized lists of hits, not for exporting millions of documents. For bulk export, other tools are more appropriate.
Results are data
Stored results consume disk, replicate to other nodes, and may contain sensitive information from your documents.
Everything expires
Each stored search has a limited lifetime. Plan on fetching results well within that time.
Responses are size-limited
A default cap of around ten megabytes stops one search from filling the store with an oversized result.
Clean-up is periodic
Expired entries disappear through a background task, not at the exact instant of expiry.
The dry cleaner has a rack with limited space. Every shirt on it takes up room, and the shop puts a maximum size on what it will take. An old shirt that nobody collects is cleared out after a set period. If everyone forgot to collect their shirts, the rack would eventually overflow.
Never try to read from, write to, or delete documents inside the system index directly. Use the async search API operations instead, which maintain the internal bookkeeping properly and respect access rules.
11Extending, Cancelling and Deleting a Search
Good housekeeping is part of using async search properly. Every search you start should have a planned ending.
Extending the lifetime
When you fetch a search, you may supply a new keep alive value. Elasticsearch then moves the expiry time forward to match. This is handy for interactive tools: as long as the user keeps a report open, the tool can quietly extend the lifetime each time it refreshes, and when the user leaves, the lifetime simply runs out and the search disappears on its own. It is much better than setting an enormous lifetime at the start “just in case.”
Cancelling and deleting
The delete operation does two jobs. If the search is still running, it cancels the underlying work, so shards stop spending effort on it as soon as they can. Then it removes the stored state and any result. This makes delete the right tool both for cleaning up finished searches and for stopping ones that are no longer wanted, such as when a user changes the filters and starts over.
Cancellation is cooperative. Shards check for cancellation at regular points while they work, so a heavy search does not stop in the same instant, but it stops quickly, and, importantly, the cluster no longer keeps merging results that nobody wants.
Cancelling is like phoning the pizza shop and saying “I no longer need the pizza.” The cook may already have rolled out the dough, but they stop before adding more toppings and baking, and the shop does not keep waiting for you to collect it.
User changes the question
The user edits a filter or time range while the previous search is still running.
Client deletes the old search
The application sends a delete for the old identifier, which cancels running work and frees any stored state.
Client submits the new search
A fresh search begins with the new conditions, and the cycle continues with a new identifier.
Problem
Abandoning searches without deleting them, for example when users navigate away or retype a query.
Why It’s Harmful
Abandoned running searches keep consuming shard resources until they finish, and abandoned finished searches occupy storage until their lifetime ends. With many users, the waste adds up quickly.
Correct Approach
Delete the previous search whenever a new one replaces it or the user leaves, and keep lifetimes short so forgotten searches clean themselves up.
12Async Search Versus Other Ways to Search
Elasticsearch offers several search styles, and each solves a different problem. Choosing the right one avoids confusion.
The family of search approaches
A regular search is the default and the best choice for anything that finishes quickly. The scroll approach, which is now discouraged for most uses, walked through large result sets by keeping a snapshot open. The point in time feature combined with a search-after parameter is the modern way to page through large results consistently. Multi-search sends several searches in one request but still waits for them all. Async search is the one designed for long-running searches where you want to detach from the connection and observe progress.
| Approach | Main purpose | Connection held? | Progress and partial results | Result stored for later? |
|---|---|---|---|---|
| Regular search | Fast queries and interactive search | Yes, until done | No, only a timeout option | No |
| Scroll | Reading large result sets in order | Per batch request | No | Kept open as a snapshot only |
| Point in time with search-after | Consistent deep paging | Per page request | No | Consistent view, not a stored result |
| Multi-search | Many searches in one round trip | Yes, until all are done | No | No |
| Async search | Long-running searches and aggregations | No, after the wait window | Yes | Yes, until expiry |
A regular search is a quick chat at the counter. Scroll and point in time are like reading a very long book one chapter at a time. Async search is like leaving a big order, getting a ticket, and being told how far along your order is. They are different tools for different situations, not better and worse versions of the same tool.
Async search and paging are different things
A common confusion is to think of async search as a way to fetch many pages of results. It is not. It returns a single response, the same shape as a normal search response, containing the hits for the requested size and the aggregations you asked for. If you need to walk through millions of documents, use a point in time with search-after, or a purpose-built export process, not a giant async search response.
Ask two questions. Will this search possibly take longer than a proxy timeout, or long enough that users need feedback? Then consider async search. Do I need to read a huge number of documents in order? Then consider point in time and search-after instead.
flowchart TD
Q["I need to run a search"] --> A{"Will it finish in a second or two?"}
A -->|"Yes"| R["Use a regular search"]
A -->|"No"| B{"Do I need progress, partial results or to detach?"}
B -->|"Yes"| AS["Use async search"]
B -->|"No"| C{"Do I need to read a very large number of documents?"}
C -->|"Yes"| PIT["Use point in time with search-after"]
C -->|"No"| R2["Regular search with a sensible timeout"]
13What Async Search Does Not Do: Limits and Misunderstandings
Knowing the boundaries of a feature is as valuable as knowing its strengths.
It does not make queries cheaper
Each shard still executes the query in full. The processing, memory and disk reads are the same as for a regular search. If a query is expensive, an async version is equally expensive. Async search is a communication improvement. If you want a query to cost less, you must improve the query, the mapping, the number of shards, the time range or the hardware.
It is not a job scheduler
Async search runs a search now, in the background. It does not schedule a search for later, repeat it every hour, or guarantee that it will run to completion after a restart. If a node involved in the search leaves the cluster or restarts, the search may fail or be incomplete. Regular reporting jobs belong in a scheduler, which can then use async search underneath if it wishes.
Some search options are restricted
Not every option of the regular search is supported in the async version. Options that are about walking through results in a stateful way, such as scroll, are not available, and the search type is limited to the standard query-then-fetch approach. Some defaults also differ from a regular search, so it is worth reading the current documentation for your version before assuming that every parameter behaves identically.
No speed-up
The same shard work happens. Only the waiting changes.
No scheduling
It starts immediately and does not repeat itself or resume after failures.
Size-limited results
Stored responses are capped, so it is not a bulk export tool.
Restricted options
Some regular search options are unsupported or default differently. Check your version.
Finite lifetime
Results vanish after expiry. It is not long-term storage.
Not a guarantee of completion
Node loss or shard failures can leave a search failed or incomplete.
Teams sometimes switch all their searches to async search hoping to fix slowness. The searches are exactly as slow as before, and now the application has extra complexity. Use async search only where its three superpowers, detaching, observing and retrieving later, actually help.
14Cluster Resources: What an Async Search Costs
A background search is still a real search. It uses real threads, real memory and real disk.
Threads and queues
Shard-level search work runs on a pool of search threads on each node. When many searches arrive at once, work waits in a queue, and if the queue is full, new work is rejected. Async searches use the same pool as regular searches, so a burst of long-running background searches can crowd out the quick interactive ones that users expect to be instant. Because async searches are longer, they hold the resources longer.
Memory on the coordinating node
The coordinating node keeps the running merged result in memory. For aggregations with many buckets, this can be large. Batched merging helps by releasing memory as it goes, but large partial results still occupy space until the search is finished and the result is handed off to storage. Circuit breakers guard against runaway memory use and will fail a search rather than risking the node.
Disk and indexing of results
When a search completes and its result is stored, Elasticsearch writes the result into the system index. That is an indexing operation with a real cost, though small compared with the search itself, and it also has to be replicated. For heavy use, hundreds of stored results of several megabytes each represent noticeable storage.
| Resource | How async search uses it | Risk if unmanaged |
|---|---|---|
| Search thread pool | Shard queries run for a long time | Queues fill and regular searches get rejected |
| Coordinating node heap | Holds the running merged result | Memory pressure and circuit breaker trips |
| Disk in the system index | Stores completed results until expiry | Growing storage from forgotten searches |
| Network | Shard results travel to the coordinator; results travel to clients | Congestion from large partial responses fetched repeatedly |
| Storage tier I/O | Slow tiers are read for old data | Long searches stacking up on slow disks or object storage |
Imagine a restaurant kitchen with a fixed number of cooks. A few huge banquet orders take up several cooks for a long time. If too many banquets arrive at once, ordinary customers wait for a simple sandwich. The kitchen has to plan for both kinds of order, or keep separate cooks for banquets.
Ways to protect the interactive experience
Limit concurrency in the application
Restrict how many async searches each user or team can have running at once, so one enthusiastic analyst cannot fill the queues.
Separate heavy workloads
Direct analytical searches to dedicated coordinating or data nodes, or to a separate cluster, so interactive search stays responsive.
Narrow the search
Reduce the time range, the number of indices, or the size of aggregations. The cheapest search is the one that touches less data.
Lean on shard skipping
Use filters on fields such as timestamps, so shards that cannot match are skipped rather than searched.
Async search lets you say yes to heavy questions without freezing a user’s screen. It is still up to you to make sure that saying yes to too many at once does not hurt everybody else.
15Cold Data, Frozen Tiers and Cross-Cluster Searches
The situations that made async search necessary are becoming more common, not less.
Data tiers and slower storage
To control costs, many organisations keep fresh data on fast, expensive nodes, and move older data to cheaper storage through several tiers. On the coldest tiers, data may live in object storage and be fetched on demand into a local cache when searched. A search that touches such data can take many seconds or longer, especially the first time, because the needed pieces must be downloaded before they can be examined.
This is a natural fit for async search. The user asks a question about last year, gets a ticket immediately, sees early results from the faster tiers, and receives the complete answer when the slower tiers finish. Without async search, the user would either face a long blank wait or be told that old data is off limits.
Recent books sit on the shelf near the library entrance and are found in seconds. Old archives are stored in a warehouse across town. Asking a librarian to fetch archive boxes takes time, so the library gives you a slip, shows you the nearby books straight away, and calls you when the boxes arrive.
Cross-cluster search
Cross-cluster search lets one cluster query others, often in different regions. The slowest remote cluster, plus network delays, sets the pace for a normal search. With async search, results from faster clusters can appear early while slower ones are still working. Partial results are especially valuable here, since some clusters may be far away or briefly unreachable, and a user would rather see most of the picture than nothing at all.
graph LR
U["User dashboard"] --> C["Local cluster: coordinating node"]
C --> H["Hot tier: fast local shards"]
C --> W["Cold tier: slower shards"]
C --> R1["Remote cluster in region 1"]
C --> R2["Remote cluster in region 2"]
H -->|"answers first"| C
W -->|"answers later"| C
R1 -->|"answers later"| C
R2 -->|"may be slowest"| C
Long-term log search
Investigators search across a year of logs stored on several tiers and want early hits from recent data.
Multi-region analytics
A global dashboard combines clusters in several regions, and the slowest region should not block the display.
Compliance lookups
Rare requests need to search archived data, accepting a longer wait in return for cheap storage.
Capacity-friendly analytics
Large aggregations run in the background on shared clusters while users continue other work.
When a remote cluster is unreachable, a search may complete with that cluster’s results missing. Always look at the shard and cluster summaries in the response, and show the user a clear note when part of the data could not be searched.
16Async Search in Kibana and Related Features
You may already be using async search without knowing it, because friendly tools rely on it behind the scenes.
Kibana and progress feedback
Kibana, the visual interface for Elasticsearch, uses async search to run many of its queries, which is why you often see a progress indicator while a large dashboard loads. Rather than hold an unbroken connection open, Kibana submits searches, polls their progress, updates the interface as results arrive, and cancels searches when you navigate away or change a filter. Understanding the pattern helps you reason about what Kibana is doing when a dashboard is slow, and about the load it places on your cluster.
Background searches and sessions
Some versions of Kibana have offered a feature that lets a user send a long search to the background and come back later to see its result, often called a search session. This relies on stored async search results with a suitable lifetime. If you use such a feature, remember that each stored session keeps data in the system index until it expires, and that the lifetimes you configure directly affect storage use.
The same pattern elsewhere
Event query language searches
Searches that look for sequences of events, common in security analytics, have an asynchronous form with the same idea: submit, check status, fetch and delete.
SQL queries
Queries written in the SQL interface can also run asynchronously, returning an identifier that can be polled and cleared.
Client libraries
Official and community client libraries wrap the async search operations, so applications can submit, poll and fetch through familiar methods instead of raw web requests.
Custom applications
Your own dashboards, reporting tools and internal portals can adopt the same pattern to give users progress bars and early results.
Async search is like the tracking page of an online parcel. You place the order once, and afterwards every view of the tracking page is a quick check on a job that is being done elsewhere. The stores and couriers that show you tracking are all using the same idea.
If you notice searches on your cluster that seem to come in bursts every time someone opens a big dashboard, the cause may be a dashboard that submits dozens of async searches at once, one per chart. Simplifying dashboards or staggering panels often reduces the load more than tuning the cluster.
17Security: Who Can See a Stored Search?
A stored result is a copy of data taken from your documents, so it must be protected like the documents themselves.
Results belong to the submitting user
When security features are enabled, each async search is tied to the user who submitted it. Other users cannot simply fetch, extend or delete that search by knowing its identifier. Administrators with sufficiently powerful privileges can typically manage other users’ searches, which is important for clean-up and for stopping runaway queries. The exact privileges required are documented for your version, and it is worth reviewing them when you design roles.
Data access rules still apply
A search submitted by a user runs with that user’s permissions. Index-level, field-level and document-level restrictions apply to the search just as they would in a normal search, so the stored result contains only what that user was allowed to see at the time. This is good news, but it also means a stored result reflects a moment in time. If permissions are later withdrawn, the stored copy may still exist until it expires or is deleted.
Treat identifiers as sensitive
Even though access is tied to the user, it is sensible to treat identifiers as sensitive and avoid pasting them into public chat channels, tickets or logs. They are handles to stored data. If an application logs identifiers for debugging, protect those logs with the same care as other operational data.
Authentication binding
The search is bound to the user who submitted it, limiting who can retrieve the result.
Permissions at run time
Index, field and document restrictions shape what the stored result contains.
Short lifetimes
The shorter the lifetime, the shorter the window in which a stored copy of sensitive data exists.
Encryption and access to disks
Stored results are on disk like other data, so disk encryption and snapshot policies matter here too.
Auditing
Audit logs can record who submitted and fetched searches, helping with investigations and compliance.
Administrative clean-up rights
Reserve the ability to manage others’ searches for trusted operators.
The dry cleaner hands each customer a slip, and staff normally check who is picking up the shirt. A slip found on the street should not be enough to walk away with someone else’s clothes. Treat your slip numbers with the same care, and ask the shop to discard old items promptly.
Problem
Using one shared service account for every user’s async searches in a multi-user application, with results stored under that single identity.
Why It’s Harmful
All users effectively share the same permissions and visibility. One user’s identifier could be used by another user’s session, and per-user restrictions are lost.
Correct Approach
Run searches under the end user’s identity where possible, or enforce strict access checks in your application layer for every identifier it hands out.
18Monitoring and Metrics
A healthy async search setup shows up in a few simple numbers. Watch them and problems announce themselves early.
What to watch
Running async searches
How many are in flight. A steady rise suggests searches are starting faster than they finish.
Time to completion
The distribution of durations, with attention to the slowest few percent, which drive user complaints.
Size of the system index
Growth in stored results. Sudden increases point to forgotten searches or unusually large results.
Search thread pool queues and rejections
Evidence that heavy background work is crowding out interactive queries.
Heap and circuit breaker trips
Signals that large partial results are stressing coordinating nodes.
Failed and partial completions
The share of searches that end with shard failures or errors, a direct measure of data quality.
Where to look
The status operation gives per-search detail. The task management view lists running search tasks, which is useful for finding long-running or stuck searches and cancelling them. Node statistics show thread pool queue lengths and rejections, and the cluster’s health and disk statistics reveal storage pressure. Slow logs help identify which queries take the longest, so that they can be improved. Your own application should also log the durations and outcomes of the async searches it submits, since it sees the entire experience from the user’s side.
flowchart LR
A["Alert: search rejections rising"] --> B["List running search tasks"]
B --> C{"Many long async searches?"}
C -->|"Yes"| D["Find owners, cancel or narrow their queries"]
C -->|"No"| E["Check regular search load and hardware"]
D --> F["Add limits on concurrent async searches per user"]
Alert on causes you can act on, such as a growing number of long-running searches or a rapidly growing system index, rather than only on the symptom of slow user experience. Early alerts leave time to act calmly.
19Failure Modes and Error Handling
Things go wrong in distributed systems. A good client is ready for each situation in advance.
| Situation | What you will see | Recommended handling |
|---|---|---|
| Identifier has expired or was deleted | A not-found error when fetching | Tell the user the result is no longer available and offer to rerun the search |
| Some shards fail during the search | Finished, with the partial flag true and failure details | Show results with a clear warning, offer a retry |
| A node holding shards restarts mid-search | Shard failures or an incomplete result | Retry the search, since work in progress is not resumed |
| Stored response would exceed the size limit | The search is marked failed | Reduce the requested size or aggregation buckets |
| Circuit breaker trips on the coordinating node | An error mentioning that data is too large | Simplify the aggregation, narrow the time range, or reduce buckets |
| Search thread queues are full | Rejections for some shard requests | Back off and retry later, and reduce concurrency |
| Client polls forever | Endless status checks for a stuck search | Set a maximum total wait, then cancel and report a timeout |
| Network drops between client and cluster | Connection errors on polling | Retry the poll; the search itself is unaffected |
The reassuring part
One of the great advantages of async search is that a dropped client connection does not destroy the search. If the network hiccups while you are polling, you can simply reconnect and poll again with the same identifier, as long as it has not expired. This is a large improvement over the regular search, where a dropped connection often means starting from scratch.
If your phone battery dies while you wait for your dry cleaning, the shirt is not lost. You charge the phone, find your slip, and pick up where you left off. Only if you wait so long that the shop clears its rack is the shirt gone.
Problem
Treating a finished search as successful without checking the partial flag and shard failure counts.
Why It’s Harmful
Missing shards mean missing data. Reports and decisions built on incomplete numbers may be quietly wrong, and the error is hard to notice later.
Correct Approach
Always inspect the completion state and shard summary. Surface warnings to users and provide an easy way to retry.
Async search does not resume interrupted work. If part of the search fails because a node restarted, the honest answer is to run it again. Design your application so that rerunning is easy, cheap in effort and clearly explained to the user.
20A Worked Example: A 90-Day Log Dashboard
Let us walk through a realistic story to see all the pieces working together.
The scenario
A retail company collects web server logs into daily indices, keeping ninety days of data. A support engineer uses an internal dashboard to see the number of errors per hour for each service over the last ninety days. The dashboard sends one search with a date histogram aggregation nested inside a terms aggregation across all ninety daily indices, which together contain around nine hundred shards. On a busy day, this search takes about forty seconds.
The old behaviour
With a regular search, the dashboard shows a blank chart for forty seconds. The office reverse proxy cuts connections after thirty seconds, so the engineer often sees a gateway error, reloads the page, and starts another heavy search, doubling the load on the cluster. Sometimes three or four of these pile up before anyone gets an answer.
The new behaviour
Submit with a two-second wait
The dashboard submits the same query as an async search with a wait of about two seconds and a keep alive of ten minutes. Nothing finishes that fast, so it receives an identifier and an initial partial result.
Show early data and a progress bar
The chart draws the first partial buckets, and a progress bar shows shards completed out of the total, updating every few seconds with gentle backoff.
The engineer spots the problem early
After fifteen seconds, the partial chart already shows a spike in errors for one service. The engineer cancels the search and applies a filter for that service.
The dashboard deletes and resubmits
The application deletes the first search, cancelling remaining work, and submits a narrower search that finishes in six seconds.
Verify completeness and clean up
When the narrower search finishes, the dashboard checks that the partial flag is false and shard failures are zero, shows the final chart, and deletes the search.
sequenceDiagram
participant E as Engineer
participant D as Dashboard
participant ES as Elasticsearch
E->>D: Open 90-day error chart
D->>ES: Submit async search (wait 2s, keep alive 10m)
ES-->>D: Id, running, partial buckets
D-->>E: Early chart and progress bar
D->>ES: Status check with backoff
ES-->>D: 30 percent of shards done
E->>D: Filter to one service
D->>ES: Delete first search
D->>ES: Submit narrower async search
ES-->>D: Finished, no failures
D-->>E: Final chart
D->>ES: Delete search
The cluster did not get any faster. What changed was that the engineer received information sooner, no connection was lost, useless work was cancelled, and the cluster ran one focused search instead of several piled-up heavy ones. The benefit came from a better conversation, not from a faster engine.
21Designing the Client: A Practical Recipe
Most of the quality of an async search experience is decided in the client code, not in the cluster.
The building blocks of a good client
A well-behaved client has five habits. It submits with a short wait so that quick searches finish in one round trip. It records the identifier as soon as it receives one. It polls the status with backoff and jitter. It checks the completion state and shard failures carefully before showing results as final. And it always deletes searches it no longer needs. If you build these five habits into a small shared library, every screen in your application gets them for free.
Short initial wait
Give the cluster a moment to answer directly, avoiding the long path for easy queries.
Remember the id
Store the identifier in your application state so a page reload can resume watching the same search.
Polite polling
Use backoff, jitter and a maximum total wait so polling never becomes a problem in itself.
Verify completeness
Check the partial flag and shard counts, and communicate any gaps clearly to the user.
Always clean up
Delete on completion, on replacement and on user departure, and keep lifetimes short as a safety net.
Limit concurrency
Cap the number of simultaneous async searches per user or per page to protect the cluster.
Designing the interface
Good interfaces label early results honestly. A small “still loading” tag, a progress bar based on shards completed, and a gentle change of colour when the search is complete let the user understand what they are looking at. Offer a visible cancel button, since the ability to stop a wrong search is one of the most valuable features of the pattern. If the search fails partway, show a clear message with a one-click retry rather than an unexplained error.
Working with proxies and gateways
Because each individual request in the pattern is short, proxy timeouts stop being a problem. The submit call returns after the short wait, each status check is quick, and the final fetch is normally quick as well. If you use long polling with a wait on the get operation, keep the wait comfortably below the shortest timeout in your chain, so that no middle machine ever cuts a request.
A good client is like a considerate customer. They place the order, keep the ticket safe, check back politely, look inside the box before accepting it, and tell the shop when they no longer need the order. A shop that has many customers like this runs smoothly.
Storing the identifier in the page address or in browser session state lets a user refresh the page and continue watching the same search, instead of starting another one. This small detail saves a surprising amount of cluster work.
22Design Patterns That Work Well
These patterns have proved themselves in many production systems.
Try fast, fall back to slow
Submit with a wait of a couple of seconds. If the answer comes back complete, render it and move on. Only when the search is still running does the interface switch to progress mode. Most searches never see the slow path.
Progressive dashboards
Render partial aggregations as soon as they are available and refine them as more shards report in, clearly labelled as provisional until the search finishes cleanly.
Cancel on change
Whenever the user changes filters or navigates away, delete the previous search before starting the next. This keeps the cluster from wasting effort on questions nobody is asking any more.
Short, extendable lifetimes
Start with a lifetime of a few minutes and extend it while the user is actively looking at the result. Forgotten searches then disappear quickly.
Per-user concurrency caps
Allow each user a small number of simultaneous async searches, queueing or refusing the rest with a friendly message.
Narrow before you widen
Encourage users to start with a small time range and expand if needed. Small searches are cheap, and they often answer the question outright.
Pre-computed summaries for the repeated heavy questions
If the same expensive aggregation is run by many people every day, compute it once on a schedule and store the summary, rather than paying for it repeatedly, even in the background.
Dedicated capacity for analytics
Route heavy analytical searches to separate nodes or a separate cluster so that they cannot harm interactive user-facing search.
graph TD
UI["User interface"] --> API["Application service with async search helper"]
API --> LIM["Concurrency limiter per user"]
LIM --> ES["Elasticsearch cluster"]
API --> STATE["Session state: current search id"]
ES --> IDX["Hidden system index for stored results"]
API -->|"delete on change or exit"| ES
23Anti-Patterns to Avoid
Recognise these habits early and you will save yourself and your cluster a lot of trouble.
Problem
Using async search for every request, including simple lookups that finish in milliseconds.
Why It’s Harmful
It adds needless complexity and extra round trips. Where a search finishes inside the wait window with no storage requested, the async form gives no benefit over a regular search.
Correct Approach
Reserve async search for searches that may be slow, and keep quick lookups on the regular search path.
Problem
Polling in a tight loop with no delay, or with a fixed short delay for searches that run for minutes.
Why It’s Harmful
Thousands of pointless requests create load and log noise, and the benefit of each additional check falls to almost nothing.
Correct Approach
Use backoff with jitter, cap the interval, and set a maximum total wait time after which the search is cancelled.
Problem
Setting very long lifetimes and never deleting results.
Why It’s Harmful
The system index grows, stored data lingers longer than necessary, and sensitive results stay around long after their usefulness has ended.
Correct Approach
Choose lifetimes to match real need, extend on demand, and delete after fetching.
Problem
Expecting async search to export millions of documents.
Why It’s Harmful
Stored responses are size-limited, and one enormous response is not a sensible way to move bulk data. The search will fail or strain the cluster.
Correct Approach
Use a point in time with search-after, or a dedicated export process, for bulk reading of documents.
Problem
Firing dozens of heavy async searches at once from a single page, one per chart, with no limits.
Why It’s Harmful
The search queues fill, interactive traffic is rejected, and the user’s page becomes slower rather than faster.
Correct Approach
Limit concurrency, stagger panels, share filters between charts, and combine related aggregations into fewer searches.
Problem
Believing that async search fixes a badly designed index, such as thousands of tiny shards or missing time filters.
Why It’s Harmful
The underlying inefficiency remains, and the cluster keeps burning resources. The problem is hidden behind a progress bar instead of being solved.
Correct Approach
Fix the data model, shard sizing and query filters first, and use async search as an interaction improvement on top of a healthy design.
24Capacity Planning for Stored Searches
A little arithmetic tells you how much space and effort a busy async search setup will need.
The three multiplying factors
The storage consumed by async search results depends on three things multiplied together: how many searches are stored at any moment, how big the average stored result is, and how many copies of the system index exist. The first factor is driven by your user numbers and by how long lifetimes are. If two hundred analysts each store five results at any one time, that is a thousand stored results. If each averages two megabytes, the store holds about two gigabytes, which is modest. If lifetimes are days long and results are never deleted, the number of stored results could grow into the tens of thousands and beyond.
| Factor | What drives it | How to control it |
|---|---|---|
| Number of stored searches | Users, dashboards, lifetimes, whether keep on completion is used | Short lifetimes, delete after use, avoid storing fast searches |
| Average result size | Number of hits returned and number of aggregation buckets | Limit hit counts, reduce bucket sizes, drop unneeded fields |
| Replication | Replica settings of the hidden system index | Accept the defaults unless you have special needs |
| Peak concurrency | How many searches run at once | Per-user caps and staggered dashboards |
A cloakroom at a busy school event needs enough hooks for the number of coats at the same time, not the total number of coats over the whole day. Coats collected promptly free their hooks. Coats left for days block hooks and force the school to buy a bigger cloakroom.
Estimating concurrency pressure
On the compute side, estimate how many async searches will be running simultaneously at peak, multiply by the average number of shards each touches, and compare with the number of search threads available across your data nodes. If the requested shard work greatly exceeds what your threads can handle, queues will grow and rejections will appear. Cutting the number of shards a search touches, through better time filters and sensible shard sizes, has an enormous effect on this calculation.
Measure a typical search
Note its duration, number of shards touched and response size, using a realistic test with realistic data.
Estimate peak users
Work out how many people are likely to run heavy searches at the same time during your busiest period.
Multiply and compare
Compare total simultaneous shard work with your search thread capacity, and total stored size with free disk space.
Add limits and headroom
Set per-user caps, lifetimes and alerts, and keep spare capacity for spikes.
Capacity for async search is usually limited by compute, not by storage. A thousand stored results are cheap; a hundred simultaneous heavy searches are not. Spend your planning effort on concurrency and on reducing the shards each search touches.
25Advantages, Disadvantages and Trade-offs
Every feature is a bargain. Here is what you gain and what you pay.
Advantages
- Frees the client from holding a long connection open
- Survives client and network hiccups, since the search continues in the cluster
- Provides progress information and partial results that improve user experience
- Allows early cancellation, saving cluster resources
- Makes searches over slow tiers and remote clusters practical
- Merges shard results in batches, reducing peak memory on the coordinating node
Disadvantages / Trade-offs
- No speed-up: the work done by the cluster is identical
- Client logic is more complex than a single request
- Stored results consume disk and must be managed and secured
- Partial results can mislead if presented as final
- Heavy background searches can crowd out interactive ones
- Some regular search options are unavailable or behave differently
Regular search compared with async search
| Aspect | Regular search | Async search |
|---|---|---|
| Client complexity | Very low, one request | Moderate, needs polling and clean-up |
| Behaviour on dropped connection | Result usually lost | Search continues, result can be fetched later |
| Progress visibility | None | Shard progress and partial results |
| Storage of results | None | Optional, until expiry |
| Suitability for very fast queries | Excellent | Unnecessary overhead |
| Suitability for long queries | Fragile | Designed for it |
Async search trades a little extra complexity for a lot of resilience and a much better experience on slow searches. On fast searches, the trade is not worth it. The skill lies in knowing which kind of search you are dealing with.
26Real-World and Industry Examples
Here is how organisations with different needs put the pattern to work.
Security operations centres
Analysts hunt for suspicious behaviour across months of logs, often spanning fast and archived tiers. Async search provides early hints while the deep archive is still being read, and cancellation prevents wasted effort when a hunt goes in the wrong direction.
Observability platforms
Engineers examine latency percentiles, error rates and traces across many services and long periods. Progressive dashboards show trends quickly and refine them, which keeps investigations moving during incidents.
E-commerce analytics
Teams compute sales and behaviour summaries across years of orders and clickstream events. Heavy analytical queries run in the background on dedicated capacity while shoppers continue to enjoy fast interactive search.
Financial and compliance reporting
Auditors run long searches over archived transactions. They accept longer waits in exchange for cheaper storage, and they rely on the completeness flags to prove that no shard was skipped.
Multi-region enterprises
Global dashboards combine several clusters. Partial results let the nearest regions show up at once while distant regions contribute when they can, with clear indicators for any region that could not be reached.
Managed and shared platforms
Platform teams provide search as a service to many internal teams. Per-user limits, short lifetimes and monitoring of stored results keep the shared cluster healthy while every team benefits from background searches.
The lesson across all these examples
In every case, the value came from respecting the difference between the computer’s timescale and the human’s. Clusters can work for a minute without complaint, but people cannot stare at nothing for a minute without frustration. Async search bridges the gap by keeping the person informed while the machine does its work, and by letting the person change their mind while work is still in progress.
27Common Myths About Async Search
A few misunderstandings appear again and again. Let us set them straight.
Myth: “Async search makes my queries faster.”
Reality: the cluster does exactly the same work. The improvement is in how the client waits, observes and recovers, not in how quickly the shards finish.
Myth: “Every async search stores its result.”
Reality: by default, a search that finishes within the wait window is returned directly and nothing is stored. Storage happens when the search is still running or when you explicitly ask to keep the result.
Myth: “Partial results are almost the final answer.”
Reality: partial results can differ greatly from the final ones, especially for rankings, minimums, maximums and averages, because data is not evenly spread across shards.
Myth: “When the running flag is false, the result is guaranteed complete.”
Reality: a finished search may have failed on some shards. You must also check the partial flag and the shard failure information.
Myth: “Results are kept forever.”
Reality: every stored search has an expiry time, after which it is deleted. Fetch what you need in good time.
Myth: “Deleting is optional housekeeping.”
Reality: deleting also cancels running work. Skipping it wastes cluster resources on searches nobody wants, and leaves stored results lying around.
Myth: “Async search can page through any amount of data.”
Reality: it returns a single, size-limited response. Bulk reading of documents belongs to other tools.
28How the Feature Evolved
A short history helps you read older articles and understand why the feature looks the way it does.
Before async search
Long searches relied on raising timeouts everywhere and hoping connections survived. Users had no visibility into progress, and cancelling was awkward.
Introduction in the 7.x series
Async search arrived in the 7.x line, around version 7.7, with submit, get and delete operations, batched merging, and stored results with a lifetime.
Status operation added
A lightweight status operation followed in a later 7.x release, making polling cheap and giving clients a completion status without downloading the whole response.
Wider adoption
Kibana and other tools adopted the pattern, and related features such as event query language and SQL gained asynchronous forms built on the same ideas.
Fit with tiered storage
As data tiers and searchable snapshots on cheaper storage became common, the value of background searches grew, since slow tiers make long searches routine.
Defaults, supported parameters and required privileges have evolved over time. Before relying on a specific behaviour, confirm it in the documentation for the exact version you run, and test it on a non-production cluster first.
29Frequently Asked Questions
Short answers to the questions beginners ask most often about async search.
It is a way to submit a search, receive an identifier and control back immediately, watch progress and partial results while it runs, and fetch the final result later, without holding a connection open.
No. The shards do the same work. What improves is the experience of waiting: you can detach, see early results, cancel, and recover from dropped connections.
Use it when a search may take long enough to hit proxy timeouts or to frustrate users, for example wide aggregations, cold tier data or cross-cluster searches. Use regular search for quick lookups.
Because the search finished within the wait window and you did not ask to keep the result, so nothing was stored. Set keep on completion to true if you want an identifier even for fast searches.
While the search runs it is always true, because you see an incomplete picture. After completion it is false if the search succeeded on all shards and true if it failed or missed some shards.
Until the expiry time shown in the response, which is based on the keep alive setting. You can extend it when you fetch, or shorten it by deleting the search.
It returns a small summary of the search, including running state, shard progress and completion code, without the potentially large results, so it is ideal for polling.
Yes. Deleting a running search cancels the underlying work and removes its stored state. Deleting a finished search removes the stored result.
With security enabled, searches are tied to the user who submitted them, so ordinary users cannot retrieve someone else’s search. Privileged administrators can typically manage them. Still, treat identifiers as sensitive.
Yes. There is a cluster setting that limits the size of a stored response, with a default of around ten megabytes. Larger responses cause the search to fail rather than being stored.
The search may finish with shard failures, marked as partial, or fail. Async search does not resume interrupted work, so rerun the search if the results are incomplete.
Start with short intervals, such as a second, and lengthen them gradually up to a modest ceiling, adding a little random jitter. Stop polling when the user leaves and set a maximum total wait.
Not sensibly. It returns a single size-limited response. Use a point in time with search-after, or a dedicated export approach, for bulk reads.
Kibana commonly uses it to run searches, which is why you see progress indicators on heavy dashboards. Related features such as event query language and SQL have their own asynchronous variants.
Treating partial or finished-but-incomplete results as final, and forgetting to delete searches. Always check completion flags and shard failures, and always clean up.
30Summary and Key Takeaways
Async search is a way of running Elasticsearch searches in the background. You submit a query, receive an identifier if the search is still running, poll a lightweight status, read partial results as shards report in, fetch the final result when it is ready, and delete the search when you are done. It solves the practical problems of long searches: broken connections, blank screens, wasted work and users who cannot change their mind. It does not make the underlying work any smaller, so it must be combined with good data modelling, sensible shard counts, narrow queries and controlled concurrency. Used with care, checking completion flags, limiting lifetimes, securing identifiers and cleaning up after itself, it turns a long, fragile wait into a calm, informative conversation between people and their data.
Key Takeaways
- Async search detaches asking from answering — you submit, get control back, and collect the result later using an identifier.
- It is a change in communication, not in speed — the shards do the same work, so expensive queries remain expensive.
- Four operations cover everything — submit, get, status and delete, with delete also cancelling running work.
- Three settings shape behaviour — the wait window, keep on completion, and keep alive decide when you get an identifier and how long results live.
- Read the flags carefully — running and partial tell different stories, and a finished search with the partial flag set may be missing data.
- Treat stored results as real data — they use disk, are size-limited, expire, and must be secured and cleaned up.
- Build a polite, careful client — short initial wait, backoff polling, concurrency limits, honest labelling of early results, and always delete when finished.