What Is Bulk Indexing Tuning in Elasticsearch?

What Is Bulk Indexing Tuning in Elasticsearch?

A complete, plain-English guide to loading huge amounts of data into Elasticsearch quickly and safely: how bulk requests travel through the cluster, which settings really matter, what to measure, and which mistakes to avoid.

Imagine moving to a new house. You could carry one item at a time: a spoon, then a plate, then a sock, walking to the truck and back every single time. Or you could pack everything into boxes and carry a full box on each trip. Boxes are obviously faster. But there is a catch. If the boxes are too small, you still spend your day walking. If they are too big, nobody can lift them and the doorway gets blocked. If ten helpers run through the same door at once, they collide. And if the new house is not ready, everything piles up in the hallway.

Loading data into Elasticsearch works in much the same way. Sending documents one at a time is the spoon-by-spoon method. The Bulk API is the box. Bulk indexing tuning is the craft of choosing the right box size, the right number of helpers, and the right house settings, so that data flows in at full speed without breaking anything. This guide starts from zero, explains what happens inside the cluster, and ends with the numbers, the settings, and the traps that matter in production.

1What Bulk Indexing Tuning Actually Is

Three plain ideas, put together: indexing, bulk, and tuning. Once each is clear, the whole subject makes sense.

Indexing means adding a document to Elasticsearch so that it can be searched. A document might be a product, a customer record, or one line from a log file. When you index it, Elasticsearch does not just save it. It also breaks the text into words, builds lookup structures, and stores the values in several shapes so that searching later is fast. That extra work is why indexing costs more than simply writing a line to a file.

The Bulk API lets you send many indexing operations in one single request. Each operation in the request says what to do (add a new document, replace one, update one, or delete one) and, for adds and replaces, carries the document itself. The cluster processes the whole batch and answers with one response that lists what happened to every item.

Tuning means adjusting the knobs that control speed. Some knobs live in your own loading program, such as how many documents go in each request and how many requests run at once. Some live in the index settings, such as how often new data becomes searchable and how many copies are kept. Some live in the cluster itself, such as the number of shards and the kind of disks. Bulk indexing tuning is the work of setting all of these knobs sensibly, using measurements instead of guesses.

Everyday Analogy

Picture a bakery that must fill a huge order of 100,000 rolls. The baker can bake one roll, sell it, and start the oven again, which wastes most of the day heating and cooling. Or the baker can load big trays into the oven, bake in large batches, and hand over full boxes. Tuning is choosing the tray size, the number of ovens, and the order in which things are done, so that the ovens are always busy but never overloaded.

5-15 MB
a common starting size for one bulk request
1 sec
default time between refreshes that make new data searchable
10%
default share of heap for the indexing memory limit
Fast indexing is not about pushing harder. It is about removing waiting.

The three places where tuning happens

Place 1

The client

Your program or ingest tool: bulk size, number of parallel workers, compression, retries, and how failures are handled.

Place 2

The index

Settings such as refresh interval, replicas, translog behavior, document ids, and the mapping that describes each field.

Place 3

The cluster

Shard count, node roles, disks, memory, and network. These set the ceiling that no client trick can break.

i
Speed Is Only One Side

Every speed-up in this guide costs something else: search freshness, safety of the data, memory, or simplicity. Good tuning is not “maximum speed.” It is the best speed you can get while keeping the promises your business needs, such as not losing data and not breaking live searches.

The one-sentence version

If you remember one line from this chapter, make it this: bulk indexing tuning is the practice of sending well-sized batches, from the right number of parallel workers, into an index whose settings favor writing, while watching the cluster’s health signals so that you go as fast as it can safely go and no faster.

2Why It Exists: The Cost of Doing Things One by One

Every tuning practice exists because something was painfully slow or dangerously fragile. Here are the pains.

Every request sent over a network carries a fixed overhead. The client opens or reuses a connection, sends a header, waits for the cluster to receive it, waits for the work, and waits for the answer. This waiting is the same whether the request carries one document or five thousand. When you index documents one at a time, you pay that overhead again and again, and most of your time goes to waiting instead of working.

A numbers walkthrough

Let us use some invented numbers to feel the difference. Suppose one round trip to the cluster costs 3 milliseconds of pure waiting, and indexing one document takes about 1 millisecond of real work. You need to load 1 million documents.

Sending them one by one, in a single line, costs about 4 milliseconds each. That is 4,000 seconds, or a bit over an hour. Now send them in bulk requests of 5,000 documents. That is 200 requests. Each one pays the 3 milliseconds of waiting once, plus the real work of indexing 5,000 documents, which is about 5 seconds if you keep the same 1 millisecond estimate. The total is roughly 1,000 seconds. Real clusters can index many documents in parallel, so with several workers you might finish in a couple of minutes. The exact figures will differ on your system, but the shape never changes: batching removes most of the waiting.

Everyday Analogy

Mailing 1,000 letters by making 1,000 separate trips to the post office wastes your day on walking. Putting them all in one sack and making a single trip is faster, even though the sack is heavier. The walk is the fixed overhead. The letters are the useful work.

A short history

1

Early days: the Bulk API arrives

Very early in Elasticsearch’s life, the Bulk API was added so that clients could group many operations into one request. It has been the standard way to load data ever since.

2

Separate thread pools for writes

Elasticsearch handled bulk and single-document writes with separate worker pools with separate queues. In later releases they were merged into a single pool named “write.”

3

Rejections as a safety valve

When too much work arrived at once, nodes started to refuse new work with an “HTTP 429 Too Many Requests” answer. This let clusters protect themselves, but it also meant that clients had to learn to slow down and retry.

4

Memory-based indexing pressure

Around version 7.9, Elasticsearch began tracking how many bytes of indexing work were in flight, and started refusing new work when a memory limit was reached. This guards the node against running out of memory, even when the queue is not yet full.

5

Today: guard rails plus good practice

The cluster protects itself much better than before. Your job is to feed it well: reasonable batch sizes, sensible parallelism, and graceful handling of the “slow down” signal.

The exact release for each step is worth double-checking in the release notes of your version. The direction of travel is what matters: from “send anything and hope” toward “the cluster pushes back, and clients cooperate.”

Why not just send as fast as possible?

A natural idea is to turn every knob to the maximum: giant batches, hundreds of workers, no pauses. The result is usually worse, not better. Giant batches consume memory on the node that receives them. Too many workers fill the queues and trigger rejections. Rejections lead to retries, and retries add more load. The cluster ends up busy handling failures instead of indexing. The goal is a steady, well-fed pipeline, like a conveyor belt that is always full but never jammed.

3Core Concepts You Need First

A dozen words explain nearly everything in this guide. Learn them here, and later chapters will read like common sense.

Data

Document and index

A document is one record. An index is a named collection of documents, like a table, that Elasticsearch searches together.

Data

Shard

An index is cut into pieces called shards, and each piece can live on a different node. A primary shard receives new documents first.

Data

Replica

A copy of a primary shard, kept on a different node for safety and for extra search capacity.

Data

Segment

A small, sealed, read-only file set inside a shard. New data lands in new segments, and background merges combine them.

Request

Bulk request

One HTTP call carrying many operations. Each line pair describes one operation. The answer lists the result of each.

Write path

Translog

A running diary on disk of recent operations, so that data can be recovered after a crash before it is fully saved in segments.

Write path

Refresh

The moment when recently indexed documents become visible to searches. By default it happens about once per second.

Write path

Flush and merge

Flush saves segments safely to disk and clears old translog. Merge combines small segments into larger ones in the background.

Traffic

Thread pool and queue

Each node has a fixed group of worker threads for writes, and a waiting line for extra work. When the line is full, new work is refused.

Traffic

Backpressure and 429

The cluster’s way of saying “slow down.” A 429 answer means the work was refused because the node was too busy.

Traffic

Throughput

How many documents, or how many bytes, go in per second. This is the main number you are trying to raise.

Traffic

Latency

How long one request takes from sending to answer. Higher batch sizes usually raise latency but also raise throughput.

The write path in one breath

When a document arrives, Elasticsearch analyzes it, meaning it turns text into searchable words. It places the result in an in-memory buffer and also records the operation in the translog on disk. At the next refresh, the buffer becomes a new small segment that searches can see. Later, a flush stores segments durably and trims the translog. Meanwhile, background merges tidy up the growing collection of small segments. Every tuning trick in this guide is really a way to make one of these steps cheaper, rarer, or more parallel.

Everyday Analogy

Think of a busy kitchen. Orders arrive on a ticket rail (the queue). The cook prepares dishes on the counter (the in-memory buffer) while a waiter writes every order in a notebook (the translog) in case the power fails. Every so often a tray of finished dishes is carried out to the dining room (refresh). At closing time the notebook is filed away (flush). During quiet moments, helpers combine small leftovers into bigger containers (merge).

Backpressure is a feature, not a bug

Beginners often see the 429 answer as an error to be suppressed. It is actually a healthy signal, similar to a traffic light turning red. The cluster is telling the client, honestly, that it needs a short pause. A well-tuned loader listens, waits a little, and tries again, ideally with a growing delay each time. A badly tuned loader either ignores the signal and loses data, or hammers harder and makes the jam worse.

Two ways to measure speed

Documents per second is easy to explain, but it depends on how large the documents are. Megabytes per second is fairer when document sizes vary. When you compare two experiments, use the same documents in both, or use bytes per second, so that you are comparing the tuning and not the data.

!
Common Trap

An HTTP 200 answer on a bulk request does not mean that every document was accepted. The request as a whole can succeed while individual items fail. Always check the per-item results, which Chapter 13 explains in detail.

4Architecture and Components

Where does a bulk request go after it leaves your program, and which parts of the cluster can slow it down?

A production cluster commonly has a load balancer in front, some nodes that act as coordinators, and many data nodes that hold the shards. The bulk request enters at the front, is taken apart by a coordinating node, and its pieces are sent to the primary shards that own each document. The primaries then pass the work on to their replicas.

flowchart TB
    Client["Indexing workers: your application or ingest tool"] --> LB["Load Balancer"]
    LB --> Coord["Coordinating Node: splits the bulk by shard"]
    Coord --> P1["Primary Shard 1"]
    Coord --> P2["Primary Shard 2"]
    subgraph NodeA["Data Node A"]
        P1
        R2["Replica of Shard 2"]
        WQA["Write thread pool and queue"]
    end
    subgraph NodeB["Data Node B"]
        P2
        R1["Replica of Shard 1"]
        WQB["Write thread pool and queue"]
    end
    P1 --> R1
    P2 --> R2
    P1 -.-> WQA
    P2 -.-> WQB
    
Figure 1: A bulk request is split by shard, executed on primaries, then copied to replicas on other nodes.

Read the picture from top to bottom. Your workers send requests through the load balancer, which spreads them across coordinating nodes. The coordinating node looks at each document’s target shard, using its id or routing value, and groups the documents by shard. Each group is sent to the node holding that primary shard. On that node the work waits in the write queue for a free worker thread. The primary indexes the documents and then forwards the same operations to each replica, which indexes them again on its own node. Notice that the replica of Shard 1 sits on Node B, next to the primary of Shard 2, so every node is doing both primary work and replica work at once.

The main components

Entry

Load balancer

Spreads client connections across nodes so that no single node becomes the doorway for all traffic.

Router

Coordinating node

Receives the bulk request, splits it by target shard, sends the pieces out, gathers the answers, and builds the final response.

Worker

Primary shard

Owns the documents of its slice. It indexes each operation first, and decides whether the operation succeeded.

Copy

Replica shard

Repeats the primary’s operations on its own copy of the data. The acknowledgment normally waits for the in-sync replicas.

Traffic control

Write thread pool

A fixed group of threads, about one per available processor, plus a waiting queue. Full queues cause 429 answers.

Memory guard

Indexing pressure

Counts the bytes of indexing work in flight at each stage and refuses new work above a limit, by default a share of the heap.

Optional

Ingest pipeline

Processing steps run on documents before indexing, such as parsing fields or adding data. Useful, but they cost extra CPU.

Storage

Disks and file system cache

Where translogs and segments are written. Fast disks and spare memory for the operating system make writes and merges much smoother.

Walking one bulk request through the machine

1

Your worker builds a batch

It collects a few thousand documents, describes each operation, and sends one request, often compressed to save network bandwidth.

2

The coordinating node checks its memory budget

The size of the request is added to the indexing pressure counter. If the limit would be exceeded, the whole request is refused with a 429.

3

The request is split by shard

Documents are grouped by the shard that owns them, and each group is sent to that shard’s primary.

4

The primary queues and indexes

The group waits for a write thread. If the queue is full, its items are refused with 429. Otherwise the documents are analyzed, buffered, and recorded in the translog.

5

Replicas repeat the work

The primary sends the operations to each in-sync replica, which indexes them independently and confirms.

6

The answer flows back

The coordinating node collects every shard’s results, assembles one response with a result for each item, and returns it to your worker.

i
Why This Matters for Tuning

Every step in this journey can be the slow one. Network limits show up at step 1, memory limits at step 2, uneven shard layout at step 3, CPU and disk at step 4, and replica lag at step 5. Tuning is largely the art of discovering which step is your bottleneck.

5Internal Working: Inside a Shard While Data Pours In

Now we open the shard itself. Most of the settings you will tune act on the small machinery shown below.

flowchart LR
    B["Incoming documents"] --> IB["In-memory indexing buffer"]
    B --> TL["Translog on disk"]
    IB -->|refresh| SEG["New small segment: now searchable"]
    SEG -->|merge| BIG["Larger merged segment"]
    TL -->|flush| COM["Lucene commit: segments saved, translog trimmed"]
    SEG --> COM
    
Figure 2: The write path inside one shard: buffer, translog, refresh, flush, and merge.
1

Analysis and structure building

Text fields are split into words, lowercased, and processed by analyzers. Each field is also turned into the structures that searches, sorting, and aggregations will need. The more fields and the more structures per field, the more CPU this step uses. It is often the biggest single cost.

2

The in-memory buffer

The results collect in memory inside the shard. Several threads can write into the same shard at once, each filling its own part of the buffer, which is why one shard can use several processor cores.

3

The translog append

At the same time, the operation is appended to the translog. By default the translog is synced to disk before each request is acknowledged, so that an acknowledged write survives a crash. That sync is a real cost on every request.

4

Refresh

Every second by default, the buffer is written out as a new small segment that searches can see. Each refresh creates new small files. Frequent refreshes mean many small segments and extra work.

5

Flush

Periodically, or when the translog grows past a size threshold, a flush makes all segments durable on disk and lets old translog files be discarded.

6

Merge

In the background, small segments are merged into bigger ones. Merging reads and writes a lot of data, so it competes with indexing for disk and CPU.

7

Throttling

If merges fall far behind, Elasticsearch deliberately slows down indexing threads so that the number of segments does not grow without limit. Throttling is a sign that disk or merge capacity is the bottleneck.

Everyday Analogy

Imagine a library receiving thousands of new books. The books are first stacked on a receiving table (buffer) while a clerk writes each title in a logbook (translog). Every second, the clerk could roll a cart of books to the shelves so patrons can see them (refresh), but each trip takes effort. Now and then the staff reorganize many small carts of books into large tidy shelves (merge). If the reorganizing staff cannot keep up, the receiving desk is told to slow down (throttling).

Why frequent refreshes hurt bulk loads

Refresh is what gives Elasticsearch its “near real-time” feel. But every refresh writes a new segment, and every new segment adds work for the future: it must be searched, and it will eventually need to be merged. During a large load, nobody is waiting for the newest document to become searchable, yet the cluster keeps refreshing every second. Loosening the refresh, as Chapter 8 explains, saves a lot of work.

Why replicas double the work

In the standard design of Elasticsearch, a replica does not simply copy files from the primary. It receives the same operations and indexes them itself, doing the analysis and buffering again. With one replica, your cluster does the indexing work twice. That is the price of safety and search capacity, and it is why turning replicas off during a first-time load can nearly halve the total indexing effort. Later, when replicas are added back, they are created by copying finished segment files, which is cheaper than indexing every document a second time.

Why the merge scheduler matters

The number of segments a shard accumulates depends on how fast it is fed and how fast it can merge. Merges are driven by a policy that groups segments of similar size. Fast disks, such as solid-state drives, allow merges to keep pace. Slow or shared disks are the classic cause of indexing that starts fast and then falls off a cliff as merges pile up.

!
The Cliff Pattern

If your load runs fast for a few minutes and then suddenly slows to a crawl, suspect merges and disk. Check the throttling numbers in the indexing statistics before you touch anything else.

6Data Flow and Lifecycle of a Bulk Load

A big load is a small project with a beginning, a middle, and an end. Most disasters happen because someone skipped the end.

flowchart LR
    S1["Plan: mapping, shards, sizing"] --> S2["Prepare: refresh off, replicas 0, translog relaxed"]
    S2 --> S3["Load: parallel bulk workers with retries"]
    S3 --> S4["Verify: counts and failed items"]
    S4 --> S5["Restore: refresh on, replicas on, translog durable"]
    S5 --> S6["Optional: force merge on read-only data"]
    S6 --> S7["Serve searches"]
    
Figure 3: The life of a one-time bulk load, from planning to serving searches.

The phases in order

1

Plan

Decide the mapping, the number of shards, and the target index name. Create the index with the right settings before any data arrives, so that Elasticsearch never has to guess field types on the fly.

2

Prepare

For a one-time load into a new index, loosen the refresh, remove replicas, and consider a relaxed translog. These settings are dynamic, so they can be changed while the index is open.

3

Load

Start parallel workers sending well-sized bulk requests. Watch the rejection counts and slow down when the cluster pushes back. Retry only the failed items.

4

Verify

Compare the number of documents in the index with the number you meant to send. Review the list of failed items and decide what to do with each.

5

Restore

Put the refresh interval back, bring replicas back to their normal number, and return the translog to full durability. Call a refresh so that everything becomes searchable at once.

6

Optional force merge

If the index will not receive more writes, merging it down to fewer segments can make searches faster and storage tidier. Do this after the load and before heavy search traffic starts.

7

Serve

Let users search. Keep an eye on the cluster while replicas finish copying, because that copy also uses disk and network.

Everyday Analogy

Think of a stage crew setting up a concert. They plan the layout, lock the doors while the equipment is carried in, and only when everything is ready do they turn on the lights and open the doors to the audience. If they open the doors halfway through the setup, the audience sees a mess and gets in the way of the crew.

!
The Restore Step Is Not Optional

One of the most common production incidents is an index left with refresh switched off and no replicas, weeks after the load finished. Searches then never see new data, and a single node failure destroys the only copy. Put the restore step in your runbook, in your script, and in your review checklist.

Three kinds of loads

Not all bulk indexing is the same, and the right tuning depends on the kind.

  • Initial load: a one-time fill of a new index from another system. Speed is the top goal. Aggressive settings are safe because you can always start again.
  • Continuous ingestion: a steady stream such as logs or events. You cannot switch off refresh or replicas, because searches and safety are needed all the time. Tuning here is about steady, efficient batches and headroom for spikes.
  • Reindexing: copying data from one index to another, usually after a mapping change. It behaves like an initial load, with the extra detail that the source index is being read at the same time.

What happens to searches during the load

With refresh loosened or switched off, new documents will not appear in search results until the next refresh. That is fine for a fresh index nobody queries yet. For an index that live users search, do not switch refresh off. Choose a longer interval, such as ten or thirty seconds, so that data still becomes visible in a reasonable time while the refresh cost drops sharply.

7Tuning the Client Side

The cheapest tuning happens in the program that sends the data. No cluster change is needed, and the gains are often large.

KnobSensible starting pointWhat to watch
Bulk request sizeAbout 5 to 15 megabytes, then adjust slowlyThroughput stops rising, or rejections and memory use climb.
Parallel workersA handful per target node, raised step by stepCPU saturation, growing queues, 429 answers.
CompressionOn, if the network is a limit and CPU is spareClient CPU usage and network throughput.
Response trimmingAsk for only the fields you need in the answerResponse size and parsing time on the client.
RetriesOnly for failed items, with a growing delayRetry storms that add load during trouble.
Connection handlingReuse connections, spread them across nodesOne node handling far more requests than the rest.
TimeoutsGenerous enough for a full batch to finishTimeouts that cause duplicate sends.

Choosing the bulk size

The right size is measured in bytes, not in document count, because documents vary in size. Elasticsearch’s own tuning guidance suggests starting with requests of roughly 5 to 15 megabytes and increasing slowly. For documents around one kilobyte, that means several thousand documents per request. Beyond a certain point, larger requests stop helping and start hurting: they consume memory on the coordinating node, they take longer to retry when they fail, and they can trigger rejections from the memory guard. There is also a hard ceiling on request size set by the HTTP settings of the cluster, which by default is 100 megabytes.

Everyday Analogy

A delivery van that carries only one parcel per trip wastes fuel. A van that is overloaded slows down, risks breaking down, and if it does break down, everything inside is late. A good driver loads the van comfortably full, not empty and not bursting.

Finding the sweet spot, step by step

1

Use one worker first

Send batches from a single worker and record documents per second at several sizes, such as 2, 5, 10, and 20 megabytes.

2

Pick the plateau

Choose the smallest size where throughput stops improving. Smaller batches are gentler and easier to retry.

3

Add workers gradually

Raise the number of parallel workers one at a time. Throughput should climb, then flatten.

4

Back off from the edge

Stop a little before the point where rejections start. A pipeline running at the very edge fails at the first spike.

Parallel workers

A single sender can rarely fill a cluster, because it spends part of its time preparing the next batch or waiting for the answer. Several workers overlap those pauses. How many workers is best depends on how many data nodes, cores, and shards you have. The rule is simple: add workers until the cluster starts pushing back or the CPU on the data nodes is fully busy, then use a comfortable amount less than that.

Compression and response trimming

Bulk bodies are text, and text compresses very well. If the network is a bottleneck, and clients typically support compressing the request, turning it on can reduce transfer time at the price of a little CPU on both ends. The response can also be trimmed: by default it lists every item in detail, which is wasteful when nearly all items succeed. Requests can ask the cluster to return only the parts of the answer that you need, for instance the error flag and the details of failed items, which cuts down both network traffic and client parsing.

Retries done right

When a batch comes back with a “too many requests” signal, do not resend it immediately. Wait, and let the wait grow if the problem persists. Adding a little randomness to the wait prevents all workers from retrying at exactly the same moment. When only some items in a batch failed, retry only those items, not the whole batch, so that you do not repeat work that already succeeded.

i
Use the Official Helpers

The official Elasticsearch client libraries include bulk helpers that handle batching by size, parallelism, retries, and per-item error reporting. Ingest tools such as Logstash and Beats also have their own batch and worker settings. The same principles in this chapter apply to them: measure the size in bytes, raise parallelism slowly, and respect rejections.

Spreading the load

If every request goes to one node, that node’s coordinating work and memory become the bottleneck while the others sit idle. Point clients at several nodes, or at a load balancer that spreads requests evenly. For large clusters, dedicated coordinating or ingest nodes can take the splitting work off the data nodes.

8Tuning the Index Settings

A handful of index settings decide how much background work every document creates. Loosening them for a load can change the speed dramatically.

SettingDefaultDuring a one-time loadAfter the load
index.refresh_interval1 secondSwitch off with -1, or use 30 seconds or moreReturn to a value your searches can live with
index.number_of_replicas10 for a first-time load that can be rerunReturn to 1 or more
index.translog.durabilitySync on every requestOptionally asynchronous, only if you can rerun the loadReturn to the request setting
index.translog.flush_threshold_size512 megabytesOptionally larger, so flushes happen less oftenReturn to default or keep if tested
indices.memory.index_buffer_size10 percent of heapNode setting, usually left aloneNo change
Document idsGenerated by ElasticsearchPrefer generated ids where possibleNo change

Most of these are dynamic index settings, so they can be changed on a running index without a restart. The memory setting is a node-level setting and needs a restart to change, so it is usually planned in advance if changed at all.

Refresh interval

Refresh makes new data searchable and creates a new small segment each time it runs. Switching it off, or stretching it to a long interval, removes a large amount of repeated work. There is one detail worth knowing: modern Elasticsearch skips scheduled refreshes on shards that nobody has searched for a while, by default around thirty seconds. That means an index that no one is querying may already refresh less often than you expect. Setting the value explicitly is still wise because it makes the behavior predictable.

Everyday Analogy

A shop that updates its window display every single second would spend all day rearranging and never selling anything. Updating the window once at the end of a big delivery is much more sensible.

Replicas

Because each replica indexes documents itself, zero replicas means your cluster does the analysis and indexing work only once. For a first-time load this can nearly double the speed. The trade-off is safety: while there are no replicas, a lost node means lost data, and the load must be redone. That is acceptable only when the source data still exists and the load can be repeated. When replicas are restored, the new copies are built from finished segment files, which is faster than replaying every document. Restoring them still uses disk and network, so plan for that time before opening the index to heavy traffic.

The translog

By default, Elasticsearch syncs the translog to disk before answering each request, so a confirmed write survives a crash. Switching to asynchronous durability syncs every few seconds instead, which saves time on each request but means that a crash can lose the last few seconds of acknowledged writes. For a load that can be rerun, that is a reasonable gamble. For continuous ingestion of data you cannot recreate, keep the safe default.

!
A Rule for Risky Settings

Only relax durability or replicas when you can answer “yes” to this question: if the whole load vanished right now, could I run it again from the source? If the answer is “no” or “not sure,” keep the safe settings.

The indexing buffer

The in-memory buffer holds recently indexed documents before they are written out as a segment. Its total size is shared among all shards that are actively indexing on the node, and it defaults to ten percent of the heap. A larger buffer means bigger, fewer segments, which is good, but the benefit shrinks as the buffer grows, and the memory comes out of the same heap that everything else needs. Most teams leave it alone, and only consider changes when a node has many busy shards.

Auto-generated ids

When you give a document your own id, Elasticsearch must first check whether a document with that id already exists in the shard, because the new operation might be a replacement. That check is real work. When Elasticsearch generates the id itself, it can skip the check, because it knows that a fresh id has never been used. For append-only data such as logs and events, generated ids make indexing noticeably faster.

The trade-off is repeatability. With your own ids, sending the same document twice simply overwrites it, which makes retries safe. With generated ids, a retry after an uncertain timeout can create a duplicate. Choose according to your data: append-only streams favor generated ids, and data that must be updated or deduplicated needs your own ids.

Things that slow indexing on purpose

  • Index sorting orders documents inside segments to help certain searches, but adds cost at indexing time. Use it only if you truly need it.
  • Stronger compression of stored data saves disk space but costs CPU while writing. The default is faster to write.
  • Waiting for extra shard copies before acknowledging adds delay. Keep the defaults unless you have a reason.
  • Refreshing on every request by asking for it in the bulk call defeats the whole point of batching.

9Mappings and Documents: Making Each Document Cheaper

The cost of indexing one document is decided long before the bulk request is sent. It is decided by the shape of the document and the mapping that describes it.

A mapping is the blueprint that tells Elasticsearch what type each field has and how it should be stored and searched. Every field you index has a price: analysis, index structures, storage for sorting and grouping, and space for the original text. The more fields and the more structures per field, the more work per document. Cutting unnecessary work at this level speeds up every single request.

Fewer fields

Index only what you search

A field that is never searched, sorted, or grouped can be marked as not indexed. It is still kept in the original document if needed.

Fewer structures

Skip what you do not use

Fields that will never be sorted or aggregated do not need the column-style storage. Text fields that will not be scored by length can drop that extra data.

Right type

Keyword versus text

Exact values like codes, ids, and statuses belong in keyword fields, which skip the heavy text analysis.

Control

Explicit mappings

Define the mapping before loading. Letting Elasticsearch guess types for every new field costs time and can guess wrongly.

Protection

Stop field explosions

Documents with thousands of different field names bloat the cluster. Limit dynamic fields, or store such maps in a special field type built for them.

Structure

Be careful with nested objects

Each nested object is stored as a hidden document of its own, so a document with many nested items costs many times more to index.

Everyday Analogy

Filling out a form with fifty boxes takes much longer than a form with ten boxes. If a box is never read by anyone, removing it saves time on every single form, and there will be thousands of forms.

Dynamic mapping: convenient but costly

When a document contains a field that the index has never seen, Elasticsearch normally creates a mapping for it automatically. This is called dynamic mapping. It is convenient for exploring but has two costs during bulk loads. First, each new field requires an update to the cluster’s shared state, which is slow when it happens often. Second, the automatic guess may be wrong or wasteful, such as indexing every string as both text and keyword. For production loads, define the mapping first, using an index template, and set dynamic behavior to strict or to off for unknown fields if your data is well understood.

Document size and shape

Very large documents are slow to analyze and take large amounts of memory in each stage of the write path. If a document contains a huge blob of text or many repeated sections, consider whether all of it must be in Elasticsearch, or whether a reference to the full content stored elsewhere would do. Documents under a few kilobytes index most smoothly.

Work before the bulk request

Cleaning, joining, and enriching data can happen in two places: in your loading program before sending, or in an ingest pipeline inside Elasticsearch. Ingest pipelines are handy, and can be attached to a request, but they spend the cluster’s CPU on work that your own program could do on cheaper machines. If the cluster is your bottleneck, moving heavy transformations upstream is one of the most effective changes you can make.

i
Templates Save the Day

An index template applies a mapping and settings automatically to every new index that matches a name pattern. For time-based data, where a new index appears every day or on every rollover, templates guarantee that each new index starts with the right blueprint and never falls back on guesswork.

10Hardware, Shards, and Cluster Layout

Settings can only take you as far as the machinery allows. This chapter covers the ceiling.

Shards: the unit of parallel work

Documents are spread across the primary shards of an index. Each shard can accept several concurrent writers, but the number of shards also decides how the work spreads across nodes. An index with a single primary shard sends all its indexing to one node, no matter how big the cluster is. An index with primaries spread over all data nodes lets every node do its share.

Too many shards cause different trouble. Each shard has fixed overhead in memory, file handles, and cluster state, and a large number of tiny shards makes both indexing and searching less efficient. A common guideline is to keep shards in the range of tens of gigabytes for search-oriented data, and to avoid a huge number of shards per gigabyte of heap. For time-series data, rolling over to a new index when the current one reaches a target size keeps shards sensible without manual planning.

Everyday Analogy

If a supermarket has one checkout lane, it does not matter how many cashiers are on the payroll; only one customer is served at a time. Ten lanes help a lot. But a hundred tiny lanes, each with its own equipment and staff, waste money and floor space.

Hardware that helps indexing

Storage

Solid-state drives

Indexing and merging create heavy, mixed disk traffic. Fast local SSDs are the most common upgrade that fixes the “starts fast, then crawls” pattern. Avoid slow network file systems.

Processor

Enough cores

Analysis is CPU-heavy, and the write thread pool is sized to the number of processors. More cores mean more documents processed at once.

Memory

Moderate heap, generous file cache

Give the heap no more than about half of the machine’s memory, and stay below the size at which Java loses compact pointers, roughly 30 gigabytes. The rest is used by the operating system to speed up disk work.

Network

Bandwidth and low latency

Replication and shard recovery copy a lot of data between nodes. A slow or busy network is a hidden bottleneck for loads with replicas.

Safety

No swapping

If the operating system moves parts of the Elasticsearch process to disk, everything becomes slow and unpredictable. Turn swapping off or lock the memory.

Roles

Dedicated node roles

Separate coordinating, ingest, and data roles on larger clusters, so that heavy transformations and request splitting do not compete with shard work.

Hot data on fast nodes

In time-based systems, the newest data is written to and searched the most, and the oldest data is mostly just stored. A layered design places the newest indices on the fastest nodes, the hot tier, and moves older indices to cheaper machines automatically. Indexing then always lands on hardware chosen for it, while cheaper hardware holds the archive.

Do the shard arithmetic before the load

Estimate the total size of the data, decide the target shard size, and divide. Then check that the result spreads evenly across your data nodes. If you have six data nodes and choose five primary shards, one node will do no primary work. Choosing six, or a multiple of six, gives every node an equal share. The number of primary shards cannot be changed on an existing index without a rebuild, so it pays to decide carefully.

i
Test Small, Then Scale

A good habit is to benchmark on one node with one shard first, to learn how many documents per second a single shard can absorb. Then multiply by the number of shards you plan to use and compare with your target. If the numbers do not add up, you learn it before the big load, not during it.

11Performance and Scalability: Finding the Bottleneck

A pipeline is only as fast as its slowest stage. Tuning the wrong stage changes nothing. The skill is knowing where to look.

Bulk indexing passes through many stages: your program, the network, the coordinating node, the write queue, the CPU that analyzes documents, the memory buffer, the translog, the disk, the merges, and the replicas. At any moment, one of these is the limit. Speeding up any other stage will not raise the total. The flowchart below is a simple way to find the limiting stage.

flowchart TD
    A["Throughput is too low"] --> B{"Are there 429 rejections?"}
    B -- Yes --> C["Reduce workers or bulk size and check queues and indexing pressure"]
    B -- No --> D{"Is data node CPU near full?"}
    D -- Yes --> E["Cut analysis cost: fewer fields, move pipelines upstream, add cores or nodes"]
    D -- No --> F{"Is the disk busy or indexing throttled?"}
    F -- Yes --> G["Improve disks, loosen refresh, check merges, add shards"]
    F -- No --> H{"Is the client the limit?"}
    H -- Yes --> I["Add workers, adjust batch size, compress, spread across nodes"]
    H -- No --> J["Check network, replicas, and uneven shard layout"]
    
Figure 4: A simple decision path for finding the bottleneck in a slow bulk load.
Everyday Analogy

Think of a factory line with five stations. If the painting station is slow, hiring more people at the packing station does nothing. You look for the station with a pile of unfinished work in front of it. In an indexing pipeline, that pile is the queue, the rejections, the high CPU, or the throttling counter.

Where the biggest wins usually are

ChangeTypical effectEffortMain risk
Use bulk requests of sensible size instead of single writesVery largeLowBatches too big for memory
Add parallel workersLargeLowRejections if overdone
Loosen or switch off refresh during loadLargeLowForgetting to restore
Remove replicas for first-time loadUp to about doubleLowNo safety copy during load
Trim the mappingMedium to largeMediumLosing features you needed
Auto-generated idsMediumLow to mediumDuplicates on retry
Faster disks and more coresLarge when hardware is the limitHighCost
More shards and nodesScales with countHighOver-sharding overhead

Read the table from top to bottom. The easiest changes are also the most powerful, so try them first. Only when they are exhausted does it make sense to change the mapping, and only after that to pay for hardware.

A worked example

Imagine a company must load 100 million product records, each about one kilobyte, into a new index within two hours. That is about 100 gigabytes of source data. Two hours is 7,200 seconds, so the target rate is roughly 14,000 documents per second, or about 14 megabytes per second.

A quick test on one node with one shard shows that a single shard absorbs about 5,000 documents per second with the default settings, and about 9,000 with refresh switched off and no replicas. To reach 14,000 per second with a safety margin, the team wants at least three shards working at once. They choose six primary shards on six data nodes, so that every node carries one primary and load is even. They start with 8-megabyte batches, and add workers until rejections just begin, then back off one step. The invented numbers are only an illustration, but the method is real: measure one shard, multiply, add margin, and verify.

Scaling out

Indexing scales nearly linearly with the number of shards and nodes, as long as the load is spread evenly and clients send to all of them. Uneven spread is the usual reason scale-out disappoints: one hot shard, or one node receiving all client traffic, becomes the limit again. Watch the per-node numbers, not only the cluster totals.

The cost of the first minutes

Many loads look fast at the start and slow later. At the start the buffers are empty, segments are few, and the file cache is cold but idle. As data grows, merges become bigger, disks become busier, and throttling may begin. Judge a tuning change by sustained throughput over a long enough run, not by the first thirty seconds.

12Advantages, Disadvantages, and Trade-offs

Every speed-up is a trade. Here is the honest balance sheet.

Advantages of tuning

  • Loads that took days can finish in hours.
  • Lower cost: the same job runs on fewer or smaller machines.
  • Fewer rejections and retries, so a steadier pipeline.
  • Less pressure on the cluster, leaving room for live searches.
  • A repeatable runbook for migrations and reindexing.
  • Better understanding of the cluster’s real limits.

Disadvantages and risks

  • Temporary settings can be forgotten and cause outages later.
  • Relaxed durability risks losing recent writes on a crash.
  • No replicas means no safety copy during the load.
  • More parallelism means more complexity and harder debugging.
  • Over-tuning for one workload can hurt another.
  • Benchmarks can mislead if the test data is unrealistic.
Trade-offLeaning toward speedLeaning toward safety
Refresh intervalLong or off: fewer segments, data invisible for a whileShort: data visible quickly, more work
ReplicasZero during load: fastest, but one failure loses dataOne or more: safe, but every document is indexed twice
Translog durabilityAsynchronous: fast, may lose the last secondsPer request: safe, slower
Bulk sizeLarge: fewer round trips, heavier memory and retriesModerate: gentler, easier to retry
Document idsGenerated: fastest, duplicates possible on retryYour own: retry-safe, extra check per document
Mapping richnessLean: fast to index, fewer search featuresRich: flexible searching, more indexing cost
ParallelismHigh: more throughput, closer to rejectionModerate: steady, with headroom for spikes
Everyday Analogy

Driving faster gets you there sooner, but you use more fuel, and you have less time to react to problems. A sensible driver goes as fast as the road, the weather, and the load allow, and slows down for corners. Tuning is choosing a safe speed for the road you have.

Which tuning fits which situation?

SituationRecommended stance
First-time migration, source data still existsAggressive: refresh off, no replicas, generated ids, restore at the end
Live index that users searchModerate: longer refresh interval, keep replicas, tune batches and workers
Continuous log or event streamSteady: safe durability, generated ids, headroom for bursts, alerts on rejections
Reindexing after a mapping changeAggressive on the new index, with careful reading load on the old one
Data that cannot be recreatedConservative: keep durability and replicas, accept slower loads

13High Availability and Reliability: When Things Go Wrong

A fast load that silently drops data is worse than a slow one. Reliability is the other half of tuning.

Partial failure: the most important idea

A bulk request is not all-or-nothing. It is a bundle of separate operations, and each one can succeed or fail on its own. The response includes a flag saying whether any item failed and then a result for each item. If your program looks only at the overall HTTP status, it will miss failures, and documents will be quietly lost. Every serious loader reads the flag, walks through the items, and handles each failure by its type.

Everyday Analogy

A courier delivers a crate of fifty parcels. The delivery note says “delivered,” but three parcels were left at the wrong address. Only by checking each parcel against the list do you find out. The overall word “delivered” is not enough.

Sorting failures into kinds

Retry

Too many requests (429)

The cluster was busy. Wait with a growing delay and resend those items. The data is fine.

Retry

Server or shard trouble (5xx)

A shard may be moving, or a node may be restarting. A retry after a pause often works. Escalate if it keeps failing.

Fix the data

Client errors (400 family)

A field has the wrong type, or the document is malformed. Retrying will never help. Send these to a separate place for inspection.

Decide

Version conflicts (409)

Happens when an operation refuses to overwrite an existing document. Treat as success or as a problem depending on your intent.

A place for the failures: the dead-letter store

Documents that can never be indexed, such as those with wrong types, should not block the pipeline or vanish. A common design writes them to a separate store, often called a dead-letter queue, along with the error message. Someone then repairs the data or the mapping and resends them. Without this, a single bad record can stall a whole load or, worse, disappear without a trace.

Timeouts and the unknown

When a request times out, you do not know whether it succeeded. The cluster may still be working on it, or it may have finished after your program stopped listening. This is why retry safety matters. With your own document ids, resending is harmless because the same document overwrites itself. With generated ids, a resent batch that had in fact succeeded creates duplicates. If duplicates are unacceptable, either use your own ids, or deduplicate later, or use generous timeouts and careful checks.

When a node fails during a load

If a node holding a primary shard goes down, one of its replicas is promoted to be the new primary, and indexing continues. With no replicas, that shard’s data is gone, and the shard is unavailable until the node returns. Because a first-time load with zero replicas has no safety net, it should be designed to be restartable: keep track of how far the load got, so that it can resume or replay a range without starting from zero.

1

Track progress

Record the last successfully indexed position from the source, such as an id range or file offset.

2

Make batches repeatable

Design each batch so that running it twice gives the same final state, usually by using stable ids.

3

Verify at the end

Compare counts between the source and the index, and inspect the dead-letter store.

4

Keep the source until verified

Do not delete the original data until the new index is confirmed complete and has its replicas.

Cluster health colors

During loads, the cluster health may show yellow when replicas are missing or still being built, and red if a primary shard is unavailable. Yellow during a zero-replica load is expected. Red is never acceptable and should stop the load until it is understood.

14Security Considerations

A loading job is a powerful client: it writes a lot of data, quickly, with credentials. It deserves careful handling.

Least privilege for loaders

Give the loading program only the permissions it needs, and only on the indices it writes. In Elasticsearch’s security model, permission to add documents is granted per index or index pattern. A loader that only creates new documents does not need rights to delete indices or read other data. Using API keys created for a single job, with a limited lifetime, is safer than sharing a general-purpose administrator account. If the key leaks, the damage is limited to what that job could do.

Everyday Analogy

A delivery driver is given a key to the loading dock, not a master key to the whole building. If the key is lost, only the dock needs to be secured.

Protect the connection

Bulk requests carry your data in text form. Always use encrypted connections between your loader and the cluster, and between nodes. Keep the cluster on a private network and expose only what the loaders and users need. Rate limiting and authentication at the load balancer add another layer.

Guard against accidental or hostile overload

  • Request size limits: the cluster caps the size of an HTTP request. Keep this cap in place, so that one huge request cannot exhaust memory.
  • Indexing pressure: the memory guard refuses work beyond its limit, which protects nodes from both mistakes and abuse.
  • Field limits: a limit on the number of fields per index stops hostile or careless documents from creating thousands of new fields.
  • Separate workloads: keep untrusted or experimental loads on their own indices, or even their own cluster, so that they cannot starve production.

Sensitive data in failures and logs

When a document fails, the error message and the failed document often end up in logs or a dead-letter store. If the data is personal or confidential, those copies become a leak risk. Restrict access to those stores, encrypt them, set retention limits, and avoid printing full document bodies in ordinary logs.

Ingest pipelines and scripts

Pipelines can run scripts and call other steps on every document. Restrict who can create or change them, because a bad pipeline changes every document that passes through, and a slow one becomes a denial-of-service against your own cluster.

!
Do Not Skip the Basics

Turn on authentication and encryption, even for internal clusters. Many data leaks come from clusters that were “only internal” and had no protection at all.

15Monitoring, Logging, and Metrics

You cannot tune what you cannot see. These are the signals to watch, and how to read them.

Elasticsearch exposes statistics for nodes and indices through its statistics endpoints, and the compact table views show several of them at a glance. Monitoring tools, including Elastic’s own, chart these over time. Keep charts of these numbers next to your throughput chart, so that a change in speed can be matched with a change in cause.

MetricWhat it tells youWarning sign
Indexing rate (documents per second)Your actual throughput, calculated from the change in the total count over timeSudden drops during a steady load
Indexing time and current indexing operationsHow long indexing takes and how many operations are in flightTime per document rising steadily
Write queue sizeWork waiting for a free worker threadQueue near its limit for long periods
Write rejectionsWork refused because of a full queueAny sustained increase
Indexing pressure memory and rejectionsBytes of indexing work in flight, and refusals by the memory guardRejections at coordinating or primary stage
Throttle timeTime indexing was deliberately slowed because merges lagAny nonzero growth
Merge activityCurrent merges and time spent mergingMerges constantly running at maximum
Segment countHow many segments each shard holdsRapid growth in number
Refresh count and timeHow often, and how expensive, refreshes areFrequent refreshes during a load
JVM heap and garbage collectionMemory health of each nodeHeap constantly high, long collection pauses
CPU, disk, and network on each nodeWhich hardware resource is the limitOne resource pinned at maximum
Failed item count from clientData that did not get inAny unexplained failures

Reading the patterns

Healthy

High rate, empty queues

Throughput is steady, rejections are absent, CPU is busy but not pinned. Leave it alone.

Overloaded

Queues full, many 429s

The cluster is being fed faster than it can work. Reduce workers or batch size, or add capacity.

Disk bound

Throttling and busy disks

Merges cannot keep up. Improve disks, loosen refresh, or slow the feed.

CPU bound

CPU pinned, disks calm

Analysis is the cost. Trim the mapping, move transformations upstream, or add cores.

Client bound

Cluster idle, client busy

The loader cannot feed fast enough. Add workers, compress, or improve the source read speed.

Uneven

One node hot, others idle

Shards or client traffic are unevenly spread. Fix layout or connection distribution.

Logging that helps

Elasticsearch can record slow indexing operations in a special log, with thresholds you choose, which helps you find the documents or fields that cost the most. On the client side, log the size of each batch, the time it took, the number of failed items, and the reasons for failure. When a load misbehaves, those logs are the first place to look.

How to benchmark honestly

1

Use realistic documents

Take a sample of real data. Synthetic documents that are smaller, simpler, or more repetitive than the real ones give flattering and useless results.

2

Start with one node and one shard

Find the rate that a single shard can absorb. Then scale by shards and nodes and compare with your target.

3

Change one thing at a time

If you change batch size and refresh interval together, you will not know which helped.

4

Run long enough

Merges and throttling appear after minutes, not seconds. A test that stops early misses the cliff.

5

Use proper tools and record results

Elastic’s benchmarking tool, Rally, can replay realistic workloads and produce comparable reports. Whatever tool you choose, write down the settings and the results of each run.

i
Alerts Worth Having

Alert on sustained write rejections, on indexing throttling, on rising failed-item counts, on heap staying near its limit, and on an index that still has refresh off or zero replicas long after a load ended.

16Design Patterns and Anti-patterns

Good habits make loads smooth and repeatable. Bad habits are the source of most late-night incidents.

Patterns that work

1

Load into a fresh index, then switch

Write the new data to a brand-new index with loading settings, verify it, restore normal settings, and then point an alias from the old index to the new one. Users never see a half-loaded index.

2

Aliases for every index

Applications read and write through aliases, not concrete index names. Swapping the alias makes migrations invisible and reversible.

3

Bounded worker pool with backoff

A fixed number of workers, each sending batches, each backing off with a growing, randomized delay when the cluster says “slow down.”

4

Dead-letter store for bad records

Records that cannot be indexed are saved with their error, so the pipeline keeps flowing and nothing is lost silently.

5

Rollover for time-based data

Write to a current index that automatically rolls over to a new one at a target size or age, keeping shards well sized and old data easy to manage.

6

Template-driven mappings

Index templates guarantee that every new index starts with the right mapping and settings.

7

A buffer in front of the cluster

For bursty sources, a message queue between producers and the loader smooths spikes, so that the cluster sees a steady flow it can handle.

Everyday Analogy

A theatre does not let the audience in while the stage is being built. It builds behind the curtain, checks everything, and only then opens the curtain. The alias swap is the curtain.

Anti-patterns to avoid

ANTI-PATTERN 01Avoid
What people do

They index documents one at a time, or in tiny batches of a few documents, from a loop in their program.

Why it hurts

Each request pays the full round-trip overhead, and each one forces its own translog sync. Throughput is a small fraction of what the cluster could do.

Better approach

Group documents into bulk requests of several megabytes, and send them from several workers in parallel.

ANTI-PATTERN 02Avoid
What people do

They ignore 429 answers, or retry them immediately in a tight loop, and keep raising the number of workers to “push through.”

Why it hurts

More pressure produces more rejections, which produce more retries. The cluster spends its energy on refusing and on repeated work, and real throughput falls.

Better approach

Treat a rejection as a signal. Back off with a growing, randomized delay, retry only the rejected items, and reduce concurrency if rejections persist.

ANTI-PATTERN 03Avoid
What people do

They switch off refresh and replicas for a load and never switch them back.

Why it hurts

New data never becomes searchable, or becomes searchable only at odd moments, and there is no safety copy if a node fails.

Better approach

Script the restore step as part of the load itself, and add an alert that looks for indices still in “loading mode.”

ANTI-PATTERN 04Avoid
What people do

They trust the overall HTTP status of a bulk request and never check the individual items.

Why it hurts

Some documents fail quietly, for example because of a wrong field type, and the loss is discovered days later.

Better approach

Read the error flag on every response, inspect failed items, route them to a dead-letter store, and compare counts at the end of the load.

ANTI-PATTERN 05Avoid
What people do

They ask for a refresh on every bulk request so that “documents are searchable right away.”

Why it hurts

Each request now creates a new segment and triggers extra work, cancelling much of the benefit of batching.

Better approach

Leave refresh to the interval setting. If some step truly must see the data, refresh once at the end of the load.

17Best Practices and Common Mistakes

A short list you could hand to a new teammate on their first day.

Best practices

Batching

Size batches by bytes

Start around 5 to 15 megabytes and adjust slowly using measured throughput.

Parallelism

Add workers gradually

Raise concurrency until rejections just begin, then step back for headroom.

Settings

Loosen for loads, restore after

Refresh and replicas are the two big levers. Write the restore step before you write the load.

Mapping

Define it first

Use templates with explicit mappings. Index only what you search.

Ids

Generated ids for append-only data

Use your own ids only when you need updates or safe retries.

Reliability

Check every item

Handle partial failures, retry the right ones, and keep a dead-letter store.

Layout

Spread evenly

Choose a shard count that divides work across all data nodes, and send requests to many nodes.

Measure

Change one thing at a time

Benchmark with real data, over long enough runs, and record every result.

Common mistakes

  • Counting documents instead of bytes. A batch of 10,000 tiny documents and a batch of 10,000 huge ones are very different loads.
  • Benchmarking with fake data. Synthetic documents that are too simple make every setting look better than it will be.
  • Changing many things at once. When speed changes, you cannot tell which change did it.
  • Sending everything to one node. The coordinating work and memory use of that node become the limit.
  • Giving the heap too much memory. A huge heap starves the file cache and lengthens garbage-collection pauses.
  • Letting dynamic mapping run wild. A stray field with thousands of names can slow the whole cluster.
  • Using updates when inserts would do. A partial update still reads the old document and writes a whole new one, so it is more expensive than adding a fresh document.
  • Forgetting that force merging is for finished data. Merging an index that still takes writes creates huge segments that are costly to keep tidy.

Myths versus facts

MythFact
The bigger the bulk request, the faster the load.Gains flatten and then reverse: large requests use more memory and cost more to retry.
More threads always means more speed.Past a point, more threads only add queueing and rejections.
A 200 status on a bulk request means everything worked.Items can fail individually inside a successful response.
Turning off replicas is always safe for a load.It is safe only if the load can be repeated from a source that still exists.
Refresh off means data is lost.Data is stored and safe. It is just not searchable until the next refresh.
Tuning is a one-time task.Data, mappings, and hardware change, so tuning should be revisited with measurements.
Partial updates are cheap.The whole document is rewritten internally.
!
A Golden Rule

Start with the easy, safe wins: proper bulk batches, a few parallel workers, and a longer refresh interval. Only take risks such as removing replicas or relaxing durability when the load can be rerun, and always restore the normal settings afterward.

18Real-World and Industry Examples

Where does bulk indexing tuning matter most?

Many well-known organizations have said publicly that Elasticsearch is part of their systems, including Wikipedia’s search, Netflix, Uber, and Stack Overflow. They rarely publish their exact loading settings, so the scenarios below are typical patterns for such workloads, not descriptions of anyone’s private configuration.

Large retailer: catalog migration

A retailer of the size of Amazon or eBay may need to load a whole product catalog into a rebuilt index after changing how products are described. Speed matters because the old and new systems run side by side. The team loads into a fresh index with refresh off and no replicas, verifies the count, restores settings, and swaps an alias. Users never see the half-finished index.

Log ingestion from thousands of servers

A streaming or ride-hailing service produces enormous volumes of log lines. Shippers on each server batch events and send them through a queue to a loader, which writes them in bulk to the current daily or rolled-over index. Here refresh cannot be off, and durability must stay safe, so tuning centers on steady batches, generated ids, headroom for spikes, and alerts for rejections.

Nightly database export

A business copies changed rows from a relational database into Elasticsearch every night. Rows are updated, not just added, so the team uses stable ids and accepts the extra check per document in return for safe retries. The batch job records how far it got, so that a failure at 3 a.m. resumes rather than restarts.

Metrics from connected devices

Thousands of devices send small readings every few seconds. A gateway groups them into larger batches before they reach the cluster, because tiny requests would waste the cluster on overhead. Data is append-only, so generated ids and time-based rollover keep everything simple and fast.

Reindexing after a mapping change

A fixed field type means a new index and a copy of all documents. The built-in reindex feature reads the old index in batches, by default of a thousand documents, and writes to the new one in bulk. Teams often raise the batch size and split the work into parallel slices, while limiting the read rate so that live searches on the old index are not harmed.

Onboarding a new customer

A multi-tenant software product imports a customer’s historical data the day they sign up. The import runs on a modest number of workers with a throttle, so that one big customer’s import does not slow everyone else’s searches.

i
The Common Thread

In every example, the winning ideas are the same: batch by size, parallelize gently, listen to the cluster, loosen settings only when safe, restore them afterward, and check every result.

19Frequently Asked Questions

Short answers to the questions that come up most often.

Q1What is a good bulk request size?
A common starting point is around 5 to 15 megabytes per request. Then adjust slowly while measuring throughput. The right value depends on document size, hardware, and mapping, so measure on your own data.
Q2How many documents should I put in one bulk request?
Count bytes, not documents. For documents of about a kilobyte, that is several thousand documents. For very large documents it can be far fewer.
Q3What does a 429 answer mean?
The node refused the work because its queue was full or because its memory limit for indexing work was reached. It is a request to slow down. Wait, then retry the refused items.
Q4Is it safe to disable refresh during a load?
Yes for the data itself: documents are stored and safe. The only effect is that they are not searchable until a refresh happens. Restore the setting, and refresh once, when the load finishes.
Q5Is it safe to set replicas to zero?
Only for loads you can repeat from a source that still exists. While there are no replicas, losing a node loses data. Restore replicas afterward and wait for them to finish copying before relying on the index.
Q6Why does my load start fast and then slow down?
Usually because merges and disk activity build up as the index grows, and Elasticsearch begins to throttle indexing. Check the throttle time, disk activity, and refresh settings, and consider faster disks.
Q7Do more shards make indexing faster?
Up to a point. More primary shards spread work across more nodes and cores. Beyond that, extra shards add overhead. Aim for a count that divides the work evenly over your data nodes and keeps shards a sensible size.
Q8Should I use my own document ids?
Use your own ids when you need updates or safe retries. Use generated ids for append-only data where speed matters more. Generated ids skip an existence check, but can create duplicates if a batch is resent after an uncertain timeout.
Q9How do I know if some documents failed?
Read the error flag in each bulk response and inspect the individual item results. Also compare the final document count in the index with what you sent.
Q10Are ingest pipelines bad for performance?
They are not bad, but they consume cluster CPU. If the cluster is your bottleneck, doing heavy transformations in your loading program, before sending, often speeds things up.
Q11Is a bulk update as cheap as adding a new document?
No. An update reads the existing document, applies the change, and writes a whole new version, marking the old one as deleted. It costs more than a plain add.
Q12What is indexing pressure?
It is the cluster’s tracking of how many bytes of indexing work are in flight. When the total passes a limit, by default a share of the heap, new work is refused to protect the node’s memory.
Q13Should I force merge after a load?
Only if the index will not receive more writes. For finished, read-only data, merging into fewer segments can help searches and tidy storage. Do not do it on an index that is still being written.
Q14How can I speed up reindexing?
Prepare the destination like any bulk load, with relaxed refresh and replicas, and consider a larger read batch size and parallel slices. Control the read rate if the source index serves live traffic.
Q15Do these settings and defaults change between versions?
Core ideas have been stable for many releases, but defaults and details can change. Always confirm in the documentation for the exact version you run.
Q16Does bulk tuning help continuous streams, or only one-time loads?
Both, in different ways. One-time loads can use aggressive, temporary settings. Continuous streams keep safe settings and gain from good batch sizing, steady parallelism, generated ids, and headroom for bursts.

20Summary and Key Takeaways

If you skim only one part of this guide, make it this one.

Bulk indexing tuning is the discipline of getting large amounts of data into Elasticsearch quickly, safely, and repeatably. It starts with batching, continues with careful settings and a lean mapping, rests on well-laid-out shards and good hardware, and is checked at every step by measurement. The cluster will tell you when you are going too fast. Your job is to listen.

Key Takeaways

  • Batch by bytes: use bulk requests of roughly 5 to 15 megabytes to start, send them from several workers, and adjust using measured throughput.
  • Listen to backpressure: a 429 answer means “slow down.” Back off with a growing delay and retry only the failed items.
  • Loosen, then restore: for one-time loads, relax refresh and replicas, and always put the normal settings back and verify afterward.
  • Make each document cheaper: define the mapping first, index only what you search, prefer generated ids for append-only data, and move heavy transformations upstream.
  • Check every result: a successful response can hide failed items, so read per-item results, keep a dead-letter store, and compare counts at the end.
  • Find the real bottleneck: look at rejections, CPU, disk, throttling, and the client in turn, and change one thing at a time.
  • Balance speed with safety and security: only take risks when the load can be rerun, give loaders least-privilege access, and monitor rejections and indexing throttling all the time.