-
Notifications
You must be signed in to change notification settings - Fork 496
[Blog] Improve OpenSearch cluster performance by separating search and indexing workloads #3772
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0f8f66f
f5c909f
ca39972
01fb796
33c47d1
1abb032
007433a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
--- | ||
layout: post | ||
title: "Improve OpenSearch cluster performance by separating search and indexing workloads" | ||
authors: | ||
- naarcha | ||
- pudyodu | ||
date: 2025-05-27 | ||
categories: | ||
- technical-posts | ||
meta_keywords: OpenSearch cluster performance, index shards, search workloads, node roles, indexing and search separation, OpenSearch benchmark, performance tuning, optimizing your cluster | ||
meta_description: Optimize OpenSearch cluster performance by separating indexing and search operations. Discover write/search replicas and dedicated search nodes, with benchmark data showing 34% lower query latency through workload separation. | ||
--- | ||
|
||
All OpenSearch indexes consist of shards, with each document in an index stored in a shard. | ||
|
||
Traditionally, OpenSearch defines two shard types: primary shards and replica shards. The primary shard handles both indexing and search operations, while replica shards maintain a copy of the primary shard's data to provide redundancy and serve search queries. You configure the number of shards at index creation time, and this number cannot be changed later without reindexing. | ||
|
||
With the introduction of segment replication and remote storage in OpenSearch, this model has evolved. In segment replication, only the primary shard node performs indexing operations and writes segment files to a remote object store—such as Amazon Simple Storage Service (Amazon S3), Google Cloud Storage, or Azure Blob Storage. Replica shards then download the segment files from the object store in parallel, eliminating the need to replay indexing operations on each replica. | ||
|
||
## What's new? | ||
|
||
To separate indexing and search workloads, we've introduced new shard roles: | ||
|
||
- **Write replicas**: Redundant copies of the primary shard. If a primary shard fails, a write replica can be promoted to primary to maintain write availability. | ||
- **Search replicas**: Serve search queries exclusively and cannot be promoted to primaries. | ||
|
||
For hardware separation between indexing and search workloads, we've introduced a new **search node role**. Primary shards and write replicas can be allocated to any node with the `data` role, while search replicas are allocated only to nodes with the `search` role. Nodes with the search role act as dedicated search-serving nodes. | ||
|
||
The following diagram shows an OpenSearch cluster with two coordinator nodes, two data nodes, and two search nodes, forming an indexing fleet and a search fleet. The index includes one primary shard, one write replica, and two search replicas. The primary shard and write replica are assigned to the data nodes, while the search replicas are assigned to the search nodes. | ||
|
||
Each component is configured to perform the following: | ||
|
||
- The remote store stores segment files and transaction logs. All replicas—including the write replica and search replicas—download segments from the remote store. | ||
- The primary shard writes both segments and transaction logs to the remote store. | ||
- The write replica downloads segments after the primary completes writing. | ||
- The search replicas continuously poll the remote store for new segments. | ||
|
||
 | ||
|
||
## Benefits | ||
|
||
Separating indexing and search workloads provides the following benefits: | ||
|
||
* **Parallel and isolated processing**: Improve throughput and predictability by isolating indexing and search. | ||
* **Independent scalability**: Scale indexing and search independently by adding `data` or `search` nodes. | ||
* **Failure resilience**: Indexing and search failures are isolated, improving availability. | ||
* **Cost efficiency and performance**: Use specialized hardware—compute optimized for indexing and memory optimized for search. | ||
* **Tuning flexibility**: Optimize performance settings like buffers and caches independently for indexing and search. | ||
* **Failure isolation**: Indexing and search issues are separated, which helps in troubleshooting failures. | ||
* **Scalable design**: Scale indexing and search independently of each other. | ||
|
||
## Enabling indexing and search separation | ||
|
||
For detailed instructions, see [Separate index and search workloads](https://docs.opensearch.org/docs/latest/tuning-your-cluster/seperate-index-and-search-workloads/). | ||
|
||
## Scale to zero with reader/writer separation: The search-only mode | ||
|
||
In write-once, read-many scenarios—like log analytics or frozen time-series data—you can reduce resource usage after indexing completes. OpenSearch now supports a **search-only mode** through the `_scale` API, allowing you to disable primary shards and write replicas while leaving only search replicas active. | ||
|
||
This significantly reduces storage and compute costs while maintaining full search capabilities, providing the following benefits: | ||
|
||
- Scale down indexing capacity when writes are no longer needed. | ||
- Free up disk and memory capacity by removing unnecessary write paths. | ||
- Work smoothly with index lifecycle controls through `_open`/`_close` operations. | ||
- Keep only search replicas active to reduce resource usage. | ||
- Maintain green cluster health with active search paths. | ||
- Auto-recover search replicas without manual intervention. | ||
- Scale back up at any time to resume indexing. | ||
- Scale search replicas based on search traffic during search-only mode. | ||
|
||
OpenSearch maintains cluster health as GREEN when search-only mode is active despite disabling primaries and write replicas. This is because only search replicas are expected to be allocated, and they are all successfully assigned. This ensures operational stability and full search availability. | ||
|
||
### How it works | ||
|
||
When the `_scale` API is called with `{ "search_only": true }`, OpenSearch performs the following operations: | ||
|
||
1. Adds an internal search-only block to the index | ||
2. Scales down all primaries and write replicas | ||
3. Keeps only search replicas active | ||
|
||
To resume indexing, run the `_scale` operation with `{ "search_only": false }`. OpenSearch restores the original index state. Even in search-only mode, cluster health remains GREEN because all expected search replicas are allocated. | ||
|
||
## Benchmark comparison | ||
|
||
We benchmarked indexing throughput and query latency across three cluster configurations using the `http_logs` workload in OpenSearch Benchmark. The test ran 50% of indexing first, followed by simultaneous indexing and an expensive multi-term aggregation query. | ||
|
||
### Cluster configurations | ||
|
||
Using [opensearch-cluster-cdk](https://github.com/opensearch-project/opensearch-cluster-cdk), we set up three different clusters on AWS. The followings table shows the node roles and associated costs based on the Amazon Elastic Compute Cloud (Amazon EC2) instance types used. Instance pricing is taken from [Amazon EC2 Instance types](https://aws.amazon.com/ec2/instance-types/). | ||
|
||
|
||
#### Cluster 1 (c1-r6g): Standard cluster with Memory Optimized instances for data nodes | ||
|
||
| Node role | Number of nodes | Instance type | Hourly cost | Total hourly cost | | ||
|--- |--- |--- |--- |--- | | ||
|Data |4 |r6g.xlarge |$0.20 |$0.81 | | ||
Check failure on line 96 in _posts/2025-05-09-improve-opensearch-cluster-performance.md
|
||
|Coordinator |2 |r6g.xlarge |$0.20 |$0.40 | | ||
Check failure on line 97 in _posts/2025-05-09-improve-opensearch-cluster-performance.md
|
||
|Cluster manager |3 |c6g.xlarge |$0.14 |$0.41 | | ||
Check failure on line 98 in _posts/2025-05-09-improve-opensearch-cluster-performance.md
|
||
| | | | |$1.62 | | ||
|
||
#### Cluster 2 (c2-c6g): Standard cluster with Compute Optimized instances for data nodes | ||
|
||
| Node role | Number of nodes | Instance type | Hourly cost | Total hourly cost | | ||
|--- |--- |--- |--- |--- | | ||
|Data |4 |c6g.xlarge |$0.14 |$0.54 | | ||
Check failure on line 105 in _posts/2025-05-09-improve-opensearch-cluster-performance.md
|
||
|Coordinator |2 |r6g.xlarge |$0.20 |$0.40 | | ||
Check failure on line 106 in _posts/2025-05-09-improve-opensearch-cluster-performance.md
|
||
|Cluster manager |3 |c6g.xlarge |$0.14 |$0.41 | | ||
Check failure on line 107 in _posts/2025-05-09-improve-opensearch-cluster-performance.md
|
||
| | | | |$1.36 | | ||
|
||
#### Cluster 3 (c3-indexing-search): Indexing-and-search-separated cluster with Compute and Memory Optimized instances for data and search nodes | ||
|
||
| Node role | Number of nodes | Instance type | Hourly cost | Total hourly cost | | ||
|--- |--- |--- |--- |--- | | ||
|Data |2 |c6g.xlarge |$0.14 |$0.27 | | ||
Check failure on line 114 in _posts/2025-05-09-improve-opensearch-cluster-performance.md
|
||
|Search |2 |r6g.xlarge |$0.20 |$0.40 | | ||
Check failure on line 115 in _posts/2025-05-09-improve-opensearch-cluster-performance.md
|
||
|Coordinator |2 |r6g.xlarge |$0.20 |$0.40 | | ||
Check failure on line 116 in _posts/2025-05-09-improve-opensearch-cluster-performance.md
|
||
|Cluster manager |3 |c6g.xlarge |$0.14 |$0.41 | | ||
| | | | |$1.49 | | ||
|
||
### Result visualizations | ||
|
||
The following charts show the indexing throughput and the query latency differences across these three clusters. | ||
|
||
The following chart compares indexing throughput across the three cluster configurations. | ||
|
||
 | ||
|
||
The following chart shows how separating workloads improves query latency. | ||
|
||
 | ||
|
||
The results show that Cluster 3 slightly outperforms the other clusters in simultaneous indexing and search while significantly reducing query latency and lowering costs. | ||
|
||
### Result metrics and comparisons | ||
|
||
The following tables provide comparisons between each cluster's benchmark results. | ||
|
||
|
||
**Comparing Cluster 1 and Cluster 3** | ||
|
||
| | |Cluster 1 (5P, 3R) |Cluster 3 (5P, 1R, 1S) |Difference | | ||
|--- |--- |--- |--- |--- | | ||
|Index throughput |Median |58523.95095 |59818.80119 |2.16462 | | ||
| |Maximum |58777.10938 |60240.02344 |2.42848 | | ||
| | | | | | | ||
|Query latency |p50 |6725.72925 |5358.19263 |-25.52235 | | ||
| |p90 |7218.57544 |5875.875 |-22.85107 | | ||
| |p99 |8073.80762 |6180.44385 |-30.63475 | | ||
| |p100 |8575.49512 |6312.8374 |-35.84217 | | ||
| | | | | | | ||
|Cost/hr | |1.62 |1.49 |-8.72483 | | ||
|
||
**Comparing Cluster 2 and Cluster 3** | ||
|
||
| | |Cluster 2 (5P, 3R) |Cluster 3 (5P, 1R, 1S) |Difference | | ||
|--- |--- |--- |--- |--- | | ||
|Index throughput |Median |58520.82413 |59818.80119 |2.16985 | | ||
| |Maximum |59169.29297 |60240.02344 |1.77744 | | ||
| | | | | | | ||
| | | | | | | ||
|Query latency |p50 |6842.04297 |5358.19263 |-27.69311 | | ||
| |p90 |7708.91797 |5875.875 |-31.19609 | | ||
| |p99 |8328.41211 |6180.44385 |-34.75427 | | ||
| |p100 |8438.39258 |6312.8374 |-33.67036 | | ||
| | | | | | | ||
|Cost/hr | |1.36 |1.49 |8.72483 | | ||
|
||
|
||
### Result summary | ||
|
||
From these comparisons, we can see that Cluster 3 is slightly better (~2% improvement) for simultaneous indexing and search workloads and has much lower query latency (~34% improvement). This is achieved with ~8% lower cost per hour compared to Cluster 1. | ||
|
||
|
||
## Conclusion | ||
|
||
Separating indexing and search workloads in OpenSearch gives you greater control over scaling, tuning, and optimizing your cluster. Whether you want to prioritize throughput, reduce latency, or manage costs, this approach helps meet the needs of modern applications. | ||
|
||
## Future work | ||
|
||
Coordinator nodes currently handle both search and indexing requests. For full separation, consider routing indexing and search traffic to distinct coordinator node groups. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Difference is in Percentage in this table and next table. Do we need to annotate it with %?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessarily, I think its implicit by the numbers. If we do make an update to the blog, I can add this to the list.