Last9

AWS OpenSearch: Setup, Performance Tips, and Practical Examples

Discover how to set up, optimize, and use Amazon OpenSearch Service with this comprehensive, step-by-step tutorial.

Jan 24th, ‘25
Amazon OpenSearch Service: The Only Tutorial You Need
See How Last9 Works

Unified observability for all your telemetry. Open standards. Simple pricing.

Talk to an Expert

Running OpenSearch on AWS means you don’t have to manage your search infrastructure. You get Elasticsearch-compatible APIs, managed by AWS, with native scaling and integration options.

This blog talks about how to set it up, index and query data, and keep things fast and stable in production. Here’s what we’ll cover:

  • Spinning up an OpenSearch domain on AWS
  • Indexing logs and JSON documents
  • Running search queries with filters, sorting, and aggregations
  • Tuning performance for low-latency reads
  • Keeping the setup secure, observable, and cost-aware

The steps are practical, CLI-focused, and aimed at helping you ship faster with fewer surprises.

What Is AWS OpenSearch Service?

AWS OpenSearch Service is Amazon's managed version of OpenSearch, an open-source search and analytics engine forked from Elasticsearch 7.10. Key features include:

  • Fully managed infrastructure
  • Elasticsearch-compatible APIs
  • Native AWS integrations
  • Auto-scaling capabilities"

You can consider it as a drop-in replacement for Elasticsearch, with AWS handling the backend operations. That includes provisioning nodes, distributing workloads, managing version upgrades, patching security vulnerabilities, and automating failover. For teams already on AWS, it offers a much lower operational footprint.

Common use cases include:

  • Centralized log collection and search (e.g., aggregating logs from ECS, EKS, or Lambda)
  • Full-text search over e-commerce catalogs, help centers, or documentation portals
  • Application monitoring and distributed tracing (when paired with OpenTelemetry)
  • Security analytics, audit logging, and alerting pipelines

The service supports both REST-based APIs and the OpenSearch Query DSL, so if you're coming from Elasticsearch, most of your existing tooling and queries will still work.

Why Run OpenSearch on AWS?

Amazon’s managed OpenSearch takes care of the underlying infrastructure, which is one of the hardest parts of operating a search and analytics system at scale.

Here’s what that includes:

  • Managed Infrastructure
    You don’t have to worry about instance provisioning, OS-level patching, or handling cluster failures. AWS automatically handles node lifecycle management, adding new nodes when needed, replacing failed ones, and rolling out updates without downtime.
  • Elastic Scaling
    Whether you're indexing a few hundred MB of logs per day or terabytes of telemetry, the service can scale up or down using instance-based capacity planning. You can manually configure instance types and counts, or use Auto-Tune to let AWS optimize settings based on usage patterns.
  • Tight AWS Integration
    OpenSearch Service works with core AWS tools.
    • Use IAM for access control.
    • Store snapshots to S3.
    • Ingest data in real-time with Lambda or Kinesis Data Firehose.
    • Monitor usage and performance via CloudWatch dashboards and metrics.
  • Built-In Security
    The service supports multiple layers of security:
    • VPC access so traffic doesn’t leave your private network
    • TLS encryption for data in transit
    • Encryption at rest with AWS KMS
    • Fine-grained access control at the index, document, and field level

If your team needs a search or analytics backend that plays well with AWS tooling and scales without manual effort, OpenSearch Service makes it easier to get started and stay reliable in production.

💡
If you're working with Python, here's a practical guide on using OpenSearch with Python that walks through indexing, querying, and handling responses.

How to set up AWS OpenSearch in 4 steps

Step 1: Set Up Your AWS OpenSearch Cluster

Before you can index or query anything, you’ll need to create a domain—AWS’s term for an OpenSearch cluster.

You can do this via the AWS Management Console, the AWS CLI, or Terraform. For this example, we’ll walk through the console setup.

Create an OpenSearch Domain

  1. Log into the AWS Console
    Navigate to the OpenSearch Service dashboard.
  2. Click “Create domain”
    Choose the deployment type. Start with "Development and testing" if you're just experimenting. For production workloads, go with “Production” to enable multi-AZ support and dedicated master nodes.
  3. Set a domain name
    Example: log-index-dev. You can’t change this later.
  4. Choose engine version
    Select the latest supported OpenSearch version unless you need backward compatibility.

Configure Cluster Resources

  • Instance type
    Choose based on workload—t3.small.search is good for dev; production setups usually use m6g or r6g series.
  • Instance count
    Start with at least 2 data nodes to avoid single-node bottlenecks. For larger workloads, add dedicated master nodes.
  • Storage type
    General Purpose (SSD) works for most cases. Use Provisioned IOPS SSD for high-throughput indexing.

Set Up Access & Security

  • Fine-grained access control
    Enable this if you want role-based access at the index or document level. You’ll also need to configure a master user here.
  • VPC access
    If you don’t want public endpoints, launch the domain inside a VPC. This gives you private networking and tighter access control.
  • IAM Policies
    You can attach IAM-based access to restrict who can read/write to the cluster from other AWS services.

Configure Data Ingestion

Once your domain is active, you can start ingesting data. A few common options:

  • Amazon Kinesis Data Firehose – stream logs from CloudWatch or other services
  • Logstash / FluentBit – for transforming and forwarding structured logs
  • Direct API requests – send data using the OpenSearch _bulk API
  • AWS Lambda – push structured events into OpenSearch from serverless workflows
  • Snapshot restore – restore a snapshot from S3 to preload indexes

Step 2: Index Data into OpenSearch

Once your OpenSearch domain is up, you want to push data for searching and analysis. You can index documents one by one or batch them efficiently with the bulk API.

1. Index a Single Document

Use curl with basic auth (good for quick tests or non-production setups):

curl -X POST "https://your-domain-name.us-east-1.es.amazonaws.com/my-index/_doc/1" \
  -H "Content-Type: application/json" \
  -u 'master-user:your-password' \
  -d '{
    "user": "alice",
    "timestamp": "2025-08-04T10:12:00",
    "message": "OpenSearch is live!"
  }' \
  -w "\nHTTP Status: %{http_code}\n"
Error handling tip:
Check the HTTP status code (curl's -w option here prints it).
Anything other than 200 or 201 means the request failed.
Example: if you get 401, check your credentials or IAM permissions.

2. Index a Single Document

In production, you should avoid static usernames/passwords. Instead, authenticate requests using AWS Signature Version 4. Here’s a way to do it using aws-cli or SDKs.

With AWS CLI:

aws opensearch index-document \
  --domain-name your-domain-name \
  --index-name my-index \
  --id 1 \
  --document '{
    "user": "alice",
    "timestamp": "2025-08-04T10:12:00",
    "message": "OpenSearch is live!"
  }'
Or you can use a SigV4 signing tool like aws-es-curl

Example using aws-es-curl to sign curl requests:

aws-es-curl -XPOST \
  "https://your-domain-name.us-east-1.es.amazonaws.com/my-index/_doc/1" \
  -d '{
    "user": "alice",
    "timestamp": "2025-08-04T10:12:00",
    "message": "OpenSearch is live!"
  }' \
  -H "Content-Type: application/json"

3. Index Multiple Documents Using Bulk API

Batch writes reduce overhead. Here’s a simple bulk request:

Curl (basic auth):

curl -X POST "https://your-domain-name.us-east-1.es.amazonaws.com/_bulk" \
  -H "Content-Type: application/x-ndjson" \
  -u 'master-user:your-password' \
  --data-binary @- <<EOF
{ "index": { "_index": "my-index", "_id": "2" } }
{ "user": "bob", "timestamp": "2025-08-04T10:15:00", "message": "Bulk write works." }
{ "index": { "_index": "my-index", "_id": "3" } }
{ "user": "carol", "timestamp": "2025-08-04T10:18:00", "message": "Streaming logs is next." }
EOF
Check response for errors:
The response JSON includes an errors field, make sure it’s false. If true, inspect the items array for failed items.

4. Bulk Indexing with Python (Using requests and requests-aws4auth for IAM Auth)

import requests
from requests_aws4auth import AWS4Auth
import boto3
import json

region = 'us-east-1'
service = 'es'
host = 'https://your-domain-name.us-east-1.es.amazonaws.com'

credentials = boto3.Session().get_credentials()
awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token)

bulk_data = '''
{ "index": { "_index": "my-index", "_id": "2" } }
{ "user": "bob", "timestamp": "2025-08-04T10:15:00", "message": "Bulk write works." }
{ "index": { "_index": "my-index", "_id": "3" } }
{ "user": "carol", "timestamp": "2025-08-04T10:18:00", "message": "Streaming logs is next." }
'''

headers = {"Content-Type": "application/x-ndjson"}
url = f"{host}/_bulk"

response = requests.post(url, auth=awsauth, headers=headers, data=bulk_data)
print("Status code:", response.status_code)
print("Response body:", response.json())

if response.status_code != 200 or response.json().get('errors'):
    print("Error indexing bulk data")

5. Bulk Indexing with Node.js (AWS SDK + axios)

const AWS = require('aws-sdk');
const axios = require('axios');
const { defaultProvider } = require('@aws-sdk/credential-provider-node');
const { SignatureV4 } = require('@aws-sdk/signature-v4');
const { Sha256 } = require('@aws-crypto/sha256-js');

const region = 'us-east-1';
const endpoint = 'https://your-domain-name.us-east-1.es.amazonaws.com';

async function signRequest(request) {
  const signer = new SignatureV4({
    credentials: defaultProvider(),
    region,
    service: 'es',
    sha256: Sha256,
  });
  return signer.sign(request);
}

async function bulkIndex() {
  const bulkData = `
{ "index": { "_index": "my-index", "_id": "2" } }
{ "user": "bob", "timestamp": "2025-08-04T10:15:00", "message": "Bulk write works." }
{ "index": { "_index": "my-index", "_id": "3" } }
{ "user": "carol", "timestamp": "2025-08-04T10:18:00", "message": "Streaming logs is next." }
`;

  let request = {
    method: 'POST',
    url: `${endpoint}/_bulk`,
    headers: {
      'Content-Type': 'application/x-ndjson',
      'Host': new URL(endpoint).host,
    },
    body: bulkData,
  };

  request = await signRequest(request);

  try {
    const response = await axios({
      method: request.method,
      url: request.url,
      headers: request.headers,
      data: bulkData,
    });
    console.log('Status:', response.status);
    console.log('Response:', response.data);
    if (response.data.errors) {
      console.error('Some documents failed to index.');
    }
  } catch (error) {
    console.error('Error indexing documents:', error);
  }
}

bulkIndex();

6. Confirm Documents Were Indexed

Basic curl search query:

curl -X GET "https://your-domain-name.us-east-1.es.amazonaws.com/my-index/_search?q=message:OpenSearch" \
  -u 'master-user:your-password' \
  -w "\nHTTP Status: %{http_code}\n"

With IAM and SigV4: Use the same AWS SDK or signing method as before to query the index securely.

💡
For setups that need to scale without managing nodes, this post on OpenSearch Serverless explains how query and indexing behavior changes in a serverless model.

Step 3: Run Search Queries in OpenSearch

Now that your data is safely indexed, it’s time to get querying. OpenSearch uses a JSON-based Query DSL (Domain-Specific Language) that gives you fine-grained control over searching and filtering documents.

1. Basic Match Query

This is the simplest search: find documents where a field contains a term (analyzed with tokenization).

Curl with basic auth:

Tip: HTTP status 200 means success. If you get 401 or 403, check your credentials or permissions.

2. Term Filter (Exact Match)

term queries search for exact values without text analysis. Use it on keyword fields.

{
  "query": {
    "term": {
      "user": "alice"
    }
  }
}

3. Range Query (Numbers or Dates)

Find documents within numeric or date ranges.

{
  "query": {
    "range": {
      "timestamp": {
        "gte": "2025-08-04T00:00:00",
        "lt": "2025-08-05T00:00:00"
      }
    }
  }
}

4. Boolean Logic (Combine Conditions)

Use bool to combine multiple queries with must (AND), should (OR), and must_not (NOT).

{
  "query": {
    "bool": {
      "must": [
        { "match": { "message": "OpenSearch" } },
        { "term": { "user": "bob" } }
      ],
      "must_not": [
        { "term": { "user": "carol" } }
      ]
    }
  }
}

5. Aggregations (Grouping + Metrics)

Calculate counts, averages, histograms, and more.

{
  "size": 0,
  "aggs": {
    "messages_by_user": {
      "terms": {
        "field": "user.keyword"
      }
    }
  }
}
Note: .keyword suffix means the aggregation is done on exact strings, not analyzed text.

Use IAM with Signed Requests

For production, avoid using basic auth in curl. Instead, use AWS Signature V4 signed requests via tools or SDKs.

Basic Match Query with IAM Auth in Python

import requests
from requests_aws4auth import AWS4Auth
import boto3
import json

region = 'us-east-1'
service = 'es'
host = 'https://your-domain-name.us-east-1.es.amazonaws.com'

credentials = boto3.Session().get_credentials()
awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token)

query = {
  "query": {
    "match": {
      "message": "OpenSearch"
    }
  }
}

url = f"{host}/my-index/_search"
headers = {"Content-Type": "application/json"}

response = requests.get(url, auth=awsauth, headers=headers, data=json.dumps(query))
print("Status code:", response.status_code)

if response.status_code == 200:
    results = response.json()
    hits = results.get('hits', {}).get('hits', [])
    print(f"Found {len(hits)} documents:")
    for doc in hits:
        print(doc['_source'])
else:
    print("Error:", response.text)

Basic Match Query with IAM Auth in Node.js

const AWS = require('aws-sdk');
const axios = require('axios');
const { defaultProvider } = require('@aws-sdk/credential-provider-node');
const { SignatureV4 } = require('@aws-sdk/signature-v4');
const { Sha256 } = require('@aws-crypto/sha256-js');

const region = 'us-east-1';
const endpoint = 'https://your-domain-name.us-east-1.es.amazonaws.com';

async function signRequest(request) {
  const signer = new SignatureV4({
    credentials: defaultProvider(),
    region,
    service: 'es',
    sha256: Sha256,
  });
  return signer.sign(request);
}

async function runSearch() {
  const query = {
    query: {
      match: { message: "OpenSearch" }
    }
  };

  let request = {
    method: 'GET',
    url: `${endpoint}/my-index/_search`,
    headers: {
      'Content-Type': 'application/json',
      'Host': new URL(endpoint).host,
    },
    body: JSON.stringify(query),
  };

  request = await signRequest(request);

  // Execute search with comprehensive error handling for common AWS OpenSearch issues
  try {
    const response = await axios({
      method: request.method,
      url: request.url,
      headers: request.headers,
      data: request.body,
    });
    console.log('Status:', response.status);
    console.log('Found', response.data.hits.total.value, 'documents');
    console.log('Hits:', response.data.hits.hits);
  } catch (error) {
    // Common AWS OpenSearch error patterns
    if (error.response?.status === 403) {
      console.error('IAM permissions insufficient for AWS OpenSearch');
      console.error('Check your IAM role has es:ESHttpGet and es:ESHttpPost permissions');
    } else if (error.response?.status === 429) {
      console.error('AWS OpenSearch rate limit exceeded');
      console.error('Consider implementing exponential backoff or reducing query frequency');
    } else if (error.response?.status === 507) {
      console.error('AWS OpenSearch cluster storage full');
      console.error('Scale up storage or implement index lifecycle management');
    } else if (error.response?.status === 400) {
      console.error('Invalid query syntax for AWS OpenSearch:', error.response?.data);
    } else if (error.response?.status === 504) {
      console.error('AWS OpenSearch query timeout - try simplifying your query');
    } else {
      console.error('AWS OpenSearch error:', error.response?.status || error.code);
      console.error('Details:', error.response?.data || error.message);
    }
  }
}

runSearch();

Step 4: Advanced Features and Performance Tips

Once your cluster is running and you're comfortable with indexing and querying, OpenSearch has several features that can improve performance, observability, and scale.

1. Tune Index Settings for Better Performance

Index-level settings can have a big impact on ingestion speed and search latency. A few key parameters to review:

  • Shard count and replicas
    When creating an index, balance your shard count based on the dataset size and query patterns. Too many shards lead to overhead; too few can create hotspots. Replicas improve read performance and fault tolerance but consume additional resources.
  • Refresh interval
    By default, OpenSearch makes new documents searchable every second. If near-real-time search isn’t required (e.g., for batch log ingestion), increasing this to 10–30 seconds can reduce disk I/O and improve indexing throughput.Example:
PUT /my-index/_settings
{
  "index": {
    "refresh_interval": "30s"
  }
}

2. Visualize Data with OpenSearch Dashboards

OpenSearch Dashboards (formerly Kibana) is included with the service and gives you a UI to explore, visualize, and share your OpenSearch data.

  • Create bar charts, time series, maps, and more using the built-in visualization tools.
  • Build dashboards to monitor logs, error rates, or application metrics in near real-time.
  • Use auto-refresh to keep charts updated with new data—especially helpful when tracking time-based logs or alerts.

Access Dashboards from the domain overview page in the AWS console, or directly at:

https://your-domain-name.us-east-1.es.amazonaws.com/_dashboards/

You’ll need to log in using the master user credentials or an IAM role with Dashboards access.

3. Stream and Preprocess Large Datasets with AWS Lambda

For high-volume or high-frequency data sources, consider using AWS Lambda as a preprocessing layer before sending data into OpenSearch.

Common patterns include:

  • Extracting structured fields from unstructured logs
  • Filtering out noise (e.g., 200 OK responses)
  • Enriching data with metadata (user agent parsing, geo-IP tagging)

Lambda can receive data from services like Kinesis, S3, or EventBridge, process it, and forward it to OpenSearch using the HTTP API or Firehose. This setup is useful when you want to keep your OpenSearch index lean and structured.

4. Detect Anomalies in Real-Time

OpenSearch includes an anomaly detection feature powered by machine learning. It’s useful for identifying unusual trends in logs or metrics—such as sudden spikes in error logs, unusual API traffic, or memory usage anomalies.

How it works:

  • You define a detector with a target index, time field, and metrics to track.
  • OpenSearch trains an unsupervised model based on historical patterns.
  • It continuously monitors incoming data and flags outliers in real time.

You can create and monitor detectors directly in OpenSearch Dashboards, and integrate findings with CloudWatch Alarms or SNS to trigger alerts.

💡
If you're comparing options or migrating from Elasticsearch, this OpenSearch vs Elasticsearch guide outlines the key differences in APIs, licensing, and performance.

Improve Search Speed and Relevancy

Good search isn’t just about fast results, it’s about showing the right ones. Here are ways to improve both performance and relevancy in OpenSearch, especially at scale.

1. Use Reranking for Better Relevance

If OpenSearch’s default scoring doesn’t cut it, reranking can help.

How it works:
You send the initial query to OpenSearch. Then, a reranker (like Cohere Rerank) reorders the top results using a machine learning model that understands language context.

When to use it:

  • When precision matters (e.g., top 3 results must be highly relevant)
  • For product search, knowledge base lookup, or recommendation systems
  • If you're already using semantic embeddings or natural language queries

Personalization:
Rerankers can optionally include user-specific context, like past clicks or preferences, for more tailored results.

2. Optimize with Intel Accelerators

If you’re running search-heavy workloads, specialized hardware can help.

Intel Accelerators improve search latency and throughput for:

  • Large-scale full-text queries
  • Vector search with dense embeddings (for semantic search)
  • High-volume indexing or multi-tenant clusters

These work well when paired with ML pipelines generating document or query embeddings, particularly in real-time applications like personalized recommendations or fraud detection.

3. Tune Indexing for Performance

The way you structure your index directly affects query speed and resource usage.

Key techniques:

  • Index only what you search
    Avoid indexing fields that are never queried. For large logs or documents, mark infrequent fields as "index": false to save on storage and CPU.
  • Use the right analyzer
    Choose analyzers (standard, keyword, custom) that match how your users search. For example, use a stemmer for natural language or a keyword tokenizer for exact matches.
  • Shard wisely
    Too many small shards create overhead. Too few lead to hotspots. Use shard allocation filtering or index rollover strategies to balance load.

4. Write Efficient Queries

Query structure affects both relevancy and latency. Here’s how to avoid common bottlenecks:

  • Avoid wildcards (*foo) on text fields—use match_phrase_prefix instead
  • Filter before sort – filters use faster structures like bitsets
  • Cache repeated queries – OpenSearch automatically caches eligible queries; keep query shapes consistent to benefit from this
  • Use size and terminate_after to limit heavy queries

For aggregations:

  • Limit buckets – top 10 terms instead of top 1000
  • Scope filters – aggregate only the data you need
  • Avoid cardinality on unoptimized fields – these are expensive and often the cause of latency spikes

5. Improve Relevance with Ranking and Synonyms

Once your queries are fast, it’s time to tune what shows up at the top.

  • Synonym handling
    Add a custom synonym filter at the index level to catch alternate terms (e.g., “TV” = “television”).
  • Behavioral feedback
    For mature systems, rerank results based on user actions—like click-through rate or dwell time—using custom scoring scripts or offline models.

Field boosting
Prioritize fields in scoring using the ^ operator. Example:

{
  "multi_match": {
    "query": "search text",
    "fields": ["title^3", "description", "tags"]
  }
}

Best Practices for Running OpenSearch in Production

OpenSearch can scale well, but to get consistent performance and efficient resource usage, you’ll want to follow a few key best practices across sharding, query design, instance selection, indexing, and monitoring.

1. Sharding Strategy

Shard count and size affect query latency, indexing speed, and memory usage.

  • Target shard size: Aim for 20–50 GB per shard.
    Too small, and you increase overhead. Too large, and you risk hitting memory or disk bottlenecks during queries or segment merges.
  • Balance shard count with workload:
    Don’t overprovision shards “just in case.” Use index lifecycle policies and rollover APIs to manage shard growth over time.

2. Optimize Requests and Queries

Query performance is often the first pain point teams hit. A few rules:

  • Filter before sorting
    Filters use fast bitsets. Sorting unfiltered data forces OpenSearch to score every document.
  • Avoid wildcard queries
    Especially leading wildcards (*error)—they can cause full index scans. Prefer match, term, or prefix queries with analyzers tailored to your data.
  • Limit aggregations
    Keep bucket sizes small (size: 10), and use filters to reduce the dataset before aggregation. Cardinality and nested aggregations are costly—use them sparingly.

3. Choose the Right Instance Types

OpenSearch performance is tightly tied to the underlying compute and storage.

  • Memory matters
    JVM-based systems like OpenSearch are memory-heavy. Use memory-optimized instances (r6g, r5) for most workloads.
  • CPU scaling
    For indexing-heavy or aggregation-heavy workloads, choose compute-optimized types (c6g, c5) with higher vCPU counts.
  • Storage
    Use EBS volumes with Provisioned IOPS if you need consistent read/write performance. General Purpose SSD (gp3) works for smaller setups. Scale storage separately from compute as needed.

4. Indexing Best Practices

Good indexing reduces memory pressure and speeds up both writes and reads.

  • Batch writes
    Group documents using the _bulk API instead of writing one at a time. This improves throughput and reduces cluster load.
  • Avoid dynamic mappings
    They consume memory and can introduce unexpected field types. Define explicit mappings whenever possible.
  • Use templates and ILM (Index Lifecycle Management)
    This keeps your index settings consistent and prevents unbounded index growth over time.

5. Monitor, Alert, and Scale

Visibility into your cluster is critical.

  • Track key metrics
    CPU usage, heap memory, disk watermark thresholds, indexing latency, and query latency are good starting points. Use Amazon CloudWatch or a custom observability backend to track these.
  • Enable Auto-Tune
    This AWS feature automatically adjusts thread pools and queue sizes based on workload patterns.
  • Set up alerting
    Use CloudWatch Alarms or your preferred alerting tool to notify you of slow queries, high CPU usage, or node failures.
  • Consider Auto Scaling
    You can configure OpenSearch Service with policies to scale the number of data nodes based on CPU or disk thresholds.

Secure Your OpenSearch Setup

Security often gets overlooked early on, but misconfigurations here can expose sensitive logs, metrics, or user data.

  • Use IAM for access control
    Apply least-privilege policies for applications, services, and users accessing OpenSearch APIs.
  • Enable encryption
    • At rest: Use AWS KMS keys to encrypt your data volumes.
    • In transit: Use TLS (HTTPS endpoints) to secure communication between clients and OpenSearch.
  • Restrict access via VPC
    Launch your OpenSearch domain inside a VPC and use security groups to restrict access to trusted IPs or subnets. Avoid exposing public endpoints unless necessary.
Probo Cuts Monitoring Costs by 90% with Last9
Probo Cuts Monitoring Costs by 90% with Last9

Control OpenSearch Costs Without Compromising Performance

Amazon OpenSearch is easy to get started with, but it’s just as easy to overspend if you’re not careful. Misconfigured shards, underutilized instances, and uncontrolled index growth can lead to steep bills, especially at scale.

A poorly sharded 100 GB dataset, for example, can cost 2–3x more than necessary, without offering any performance benefit.

Here’s how to avoid that.

1. Use Reserved Instances for Predictable Workloads

If your cluster usage is steady, Reserved Instances (RIs) can reduce costs by 20–30% compared to on-demand pricing.

  • Ideal for production clusters with fixed instance types and counts
  • Choose 1-year or 3-year commitments depending on workload stability
  • Works well for dedicated data nodes and master nodes

Before purchasing RIs, review usage patterns via AWS Cost Explorer or CloudWatch metrics to make sure your workload justifies it.

2. Right-Size Shards and Indices

Shard and index mismanagement is one of the fastest ways to burn through your OpenSearch budget.

  • Avoid oversharding: Dozens of small indices or low-volume shards increase memory and file descriptor usage. Each one adds overhead, even if it holds only a few MBs of data.
  • Target 20–50 GB per shard: This balances search performance and memory use for most workloads.
  • Use rollover and ILM policies: Automatically rotate logs and expire cold data to control index sprawl and disk usage.

Small changes here, like consolidating log indices or reducing daily index creation, can dramatically reduce both compute and storage usage.

3. Monitor Key Cost Drivers with CloudWatch

Track and alert on metrics that tend to spike costs unexpectedly:

  • Instance hours – check for underutilized or oversized nodes
  • Heap usage – consistently high memory pressure leads to scaling and extra charges
  • Shard count – especially important when using dynamic indexing strategies
  • Indexing/query throughput – high volumes may require better instance types, not just more of them

Set up CloudWatch alarms to catch anomalies early, and use AWS Cost and Usage Reports (CUR) for a detailed breakdown of spend across regions and resources.

Conclusion

Amazon OpenSearch Service offers a flexible way to handle search and analytics workloads, whether you're building log pipelines, powering product search, or analyzing operational data. But like any large-scale system, performance, cost, and observability start to matter quickly.

At Last9, we’ve worked with teams running OpenSearch at scale, across log analytics, security monitoring, and real-time dashboards. If you're looking to monitor OpenSearch clusters more effectively, reduce telemetry costs, or identify performance drift early, Last9 helps make that part easier.

And if you're just getting started, following these practices puts you in a good place to scale without surprises.

FAQs

What is Amazon OpenSearch Service?

Amazon OpenSearch Service is a fully managed service that makes it easy to deploy, operate, and scale OpenSearch clusters for search and analytics workloads. It provides real-time log and event data processing, full-text search, and powerful analytics capabilities.

How do I set up an OpenSearch cluster?

To set up an OpenSearch cluster, you can use the AWS Management Console. Start by creating a domain, configuring settings like instance type, storage options, and access policies, and then ingesting data. You can also use AWS SDKs to automate the process.

Can I integrate OpenSearch with AWS Lambda?

Yes, you can integrate OpenSearch with AWS Lambda. Lambda functions can be used to preprocess data before ingesting it into OpenSearch, such as filtering logs or transforming data into the right format for search.

How do I secure my OpenSearch Service cluster?

To secure your OpenSearch cluster, you can use IAM roles for fine-grained access control, enable encryption for both data in transit and at rest, and set up VPC endpoints to restrict access to your cluster within a private network.

What are some best practices for optimizing OpenSearch performance?

To optimize performance, consider fine-tuning shard allocation, using batch indexing instead of real-time indexing, selecting the right instance types, and optimizing queries and index settings. Regularly monitor your cluster for any bottlenecks and adjust accordingly.

What is the difference between OpenSearch and Elasticsearch?

OpenSearch is a community-driven, open-source search and analytics suite derived from Elasticsearch 7.x. While both are similar in functionality, OpenSearch includes additional features, improved licensing, and greater community involvement, following the transition after Elasticsearch changed its licensing model.

How can I scale my OpenSearch Service cluster?

You can scale your OpenSearch cluster by increasing or decreasing the number of nodes and adjusting instance sizes based on your workload. Amazon OpenSearch Service also offers auto-scaling policies to automatically adjust your cluster’s capacity in response to changes in traffic or data volume.

Authors
Anjali Udasi

Anjali Udasi

Helping to make the tech a little less intimidating. I

tags

Contents

Do More with Less

Unlock unified observability and faster triaging for your team.