NEW

Pulse 2025 Product Roundup: From Monitoring to AI-Native Control Plane

Elasticsearch index.merge.policy.segments_per_tier Setting

index.merge.policy.segments_per_tier is a per-index setting that tunes Lucene's TieredMergePolicy. It controls how many segments are allowed in each size tier before the policy schedules a merge. Lower values mean more aggressive merging - fewer segments, faster search, more write amplification. Higher values mean lazier merging - more segments, slower search, less indexing overhead. The setting is one of the more nuanced merge tuning knobs and rarely needs adjustment for typical workloads.

  • Default: 10
  • Scope: Per-index, dynamic - update via the update settings API
  • Possible values: Any value ≥ 2 (and ≥ index.merge.policy.floor_segment-related constraints)

How segments_per_tier Works

Lucene's tiered merge policy groups segments into size tiers and merges them when a tier has too many. segments_per_tier sets the per-tier threshold. A value of 10 means each tier can hold roughly 10 segments before a merge fires. The total segment count on an index is approximately segments_per_tier * log(total_size / floor_segment).

Lower values force more frequent merges, keeping search-time segment count low. The trade-off is write amplification: each byte written may be re-written several times as small segments are merged into bigger ones.

Configuring segments_per_tier

Update dynamically:

PUT /my_index/_settings
{
  "index": {
    "merge.policy.segments_per_tier": 8
  }
}

Apply to new indices via index templates so existing indices aren't affected without intent.

Tuning Guidance

Workload Recommendation
Mixed read/write, default Elasticsearch use Leave at 10
Read-heavy (search-dominated) 4-8 - fewer segments, faster search
Write-heavy, append-only logs 12-20 - reduce merge overhead
Time-series with rollover Default, but force-merge to 1 segment after rollover
Bulk reindex into a new index Raise to 24+ during reindex, then force-merge

After raising the setting, the index will gradually drift toward a higher segment count. Lowering it triggers extra merges immediately.

Setting Default Purpose
index.merge.policy.max_merge_at_once 10 Max segments combined in one normal merge
index.merge.policy.max_merged_segment 5gb Cap on segment size produced by merging
index.merge.policy.floor_segment 2mb Segments below this are treated as equal size when tiering
index.merge.scheduler.max_thread_count max(1, processors/2) Concurrent merge threads

Tuning segments_per_tier alone usually under-delivers. Pair changes with max_merged_segment (if you want fewer large segments) and the scheduler thread count (if merges are CPU-bound).

Common Pitfalls

  1. Lowering segments_per_tier while ingestion rate is high. The cluster falls behind on merges and indexing throughput drops sharply.
  2. Raising it without monitoring segment count. Search latency creeps up because every query consults more segments.
  3. Comparing segment count across very different shard sizes. A 50 GB shard at segments_per_tier: 10 will have far more segments than a 5 GB one - that's expected.
  4. Treating the setting as a substitute for force_merge. Force-merge is the right tool for end-of-life indices that should be compacted permanently.

Monitoring Merge Behavior

Useful APIs:

GET /_cat/segments/my_index?v&s=index,segment&h=segment,size,docs.count,merge
GET /_nodes/stats/indices/merges
GET /_cat/recovery

Watch for:

  • Total segment count per shard creeping up over time
  • Merge throttle time (indices.merges.total_throttled_time_in_millis)
  • Search latency p95 correlation with segment count

Prevent segments_per_tier Misconfiguration with Pulse

Pulse is an AI DBA for Elasticsearch and OpenSearch that tracks index.merge.policy.segments_per_tier (default 10) along with max_merged_segment (default 5gb), floor_segment (default 2mb), and merge scheduler thread count, flagging:

  • Drift between template intent and actual per-index settings, especially after PUT /<index>/_settings calls that override templates
  • Settings that are unsafe for your workload (e.g. lowered to 4 on a write-heavy index causing merge throttling, or raised to 24 during a reindex and never restored)
  • The downstream operational impact: total segment count per shard, merge throttle time (indices.merges.total_throttled_time_in_millis), and the search latency p95 correlation with segment count

When merge backpressure starts producing write rejections, Pulse names the index, the tier ratio, and the segments_per_tier value behind it - so operators discover merge problems while they are still tunable, not after they cause indexing rejections.

Connect your cluster.

Frequently Asked Questions

Q: What is the default value of index.merge.policy.segments_per_tier?
A: The default is 10. Lucene's tiered merge policy tolerates approximately 10 segments per size tier before scheduling a merge. The setting can be lowered for search-heavy indices or raised for ingest-heavy ones.

Q: How does segments_per_tier affect indexing performance?
A: Lower values mean more frequent merges, which use more CPU and IO and amplify write throughput. Higher values reduce merge overhead but leave more segments around. A doubled value roughly halves the merge cost per byte ingested.

Q: How does segments_per_tier affect search performance?
A: Each search consults every segment, so more segments mean slower searches. Halving segments_per_tier roughly halves the segment count, which can improve search latency by 10-30% for term and range queries.

Q: Can I change segments_per_tier on a live index?
A: Yes, it's a dynamic setting. New merges immediately follow the new value. Existing segments aren't re-merged unless they happen to be selected by the next merge cycle - the effect is gradual.

Q: Should I use force_merge instead of tuning segments_per_tier?
A: They solve different problems. force_merge compacts a non-changing index into a target segment count and is appropriate for rolled-over or read-only indices. segments_per_tier controls steady-state merge behavior on an actively-written index.

Q: Is segments_per_tier per-shard or per-index?
A: The setting is per-index but applies to every shard independently. A shard with more data will end up with more segments at the same threshold.

Q: What's the best tool to tune Elasticsearch merge policy and catch segment-count problems early?
A: Pulse is built for this. It is an AI DBA for Elasticsearch and OpenSearch that continuously tracks segments_per_tier, segment count per shard, merge throttle time, and the correlation with search latency, recommending merge-policy adjustments while they are still preventive rather than reactive.

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.