Application search does not always require a managed Elasticsearch service. For teams that want more control over infrastructure, deployment, configuration, and operating costs, OpenSearch can be deployed and managed directly.
OpenSearch provides search and indexing capabilities that can support product search, document search, log analysis, internal portals, and other applications that need more than a traditional database query.
The important part is understanding what you take responsibility for when you operate OpenSearch yourself.
A self-managed search system gives you control, but you also become responsible for capacity planning, backups, upgrades, security, monitoring, and failure recovery.
This article explains how to build an application search setup with OpenSearch without depending on a managed Elasticsearch service.
What Self-Managed OpenSearch Means
With a managed search service, the provider usually handles much of the underlying infrastructure.
With self-managed OpenSearch, your team operates the search cluster.
A simplified architecture looks like this:
Application
|
v
Search API
|
v
OpenSearch Cluster
|
+-- Indexes
+-- Shards
+-- Replicas
+-- StorageThe application should normally communicate with OpenSearch through a controlled service boundary rather than allowing every part of the application to access the cluster directly.
For example:
Web Application
|
v
Search Service
|
v
OpenSearchThis keeps search-specific logic in one place.
When OpenSearch Makes Sense
OpenSearch can be a good choice when an application needs:
Full-text search
Filtering
Sorting
Search suggestions
Faceted navigation
Aggregations
Large searchable document collections
Flexible indexing
Search ranking
It can also be useful when the team already has infrastructure for running stateful services.
However, self-managing OpenSearch is not automatically simpler than using a managed service.
The operational requirements should be considered before choosing the architecture.
Basic OpenSearch Architecture
A production deployment normally contains more than one OpenSearch node.
A simplified cluster might look like:
Application
|
v
Search Service
|
v
Load Balancer
|
+----------+----------+
| | |
v v v
OpenSearch OpenSearch OpenSearch
Node 1 Node 2 Node 3
| | |
+----------+----------+
|
v
Persistent StorageMultiple nodes provide better availability and allow data and search workload to be distributed across the cluster.
The exact topology depends on workload size and availability requirements.
Start With a Development Environment
Before deploying a cluster, start with a small local environment.
A containerized setup is convenient for development because it allows the application team to run OpenSearch without installing the entire stack directly on the operating system.
For example:
services:
opensearch:
image: opensearchproject/opensearch:latest
environment:
- discovery.type=single-node
- DISABLE_SECURITY_PLUGIN=true
- OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m
ports:
- "9200:9200"The exact image version should be pinned for repeatable development environments.
Avoid using an unpinned latest tag in production.
Connect a Rails Application
A Rails application can communicate with OpenSearch through an HTTP client or a compatible Ruby library.
A simple service object can keep search logic separate from controllers.
class ProductSearch
def initialize(client)
@client = client
end
def search(query)
@client.search(
index: "products",
body: {
query: {
multi_match: {
query: query,
fields: ["name", "description"]
}
}
}
)
end
endThe exact client depends on the application's OpenSearch integration.
The important design principle is to avoid scattering raw search requests throughout controllers and models.
Connect a .NET Application
A .NET application can also isolate OpenSearch access behind a dedicated service.
For example:
public class ProductSearchService
{
private readonly HttpClient _client;
public ProductSearchService(HttpClient client)
{
_client = client;
}
public async Task<string> SearchAsync(string query)
{
var request = new
{
query = new
{
multi_match = new
{
query,
fields = new[]
{
"name",
"description"
}
}
}
};
var response = await _client.PostAsJsonAsync(
"products/_search",
request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}In a production application, map the response into application-specific models instead of returning raw JSON throughout the application.
Create an Index Mapping
Search quality depends heavily on how documents are indexed.
For example:
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"category": {
"type": "keyword"
},
"price": {
"type": "double"
},
"createdAt": {
"type": "date"
}
}
}
}The distinction between text and keyword fields is important.
A text field is generally used for full-text search.
A keyword field is generally useful for exact matching, filtering, grouping, and sorting.
Choosing the wrong field type can make application queries harder or less efficient later.
Keep Database Data and Search Data Separate
OpenSearch should usually be treated as a search-oriented representation of application data.
For example:
PostgreSQL
|
| Source of truth
v
Application
|
| Indexing pipeline
v
OpenSearch
|
v
Search ResultsDo not automatically treat OpenSearch as the authoritative transactional database.
Your application database may contain relationships, transactions, constraints, and business rules that do not belong in the search index.
The search index should contain the data required to answer search requests efficiently.
Index Documents From the Application
Suppose the application stores products in a relational database.
A search document might contain:
{
"id": 101,
"name": "Wireless Keyboard",
"description": "Compact keyboard for office use",
"category": "accessories",
"price": 79.99
}The application can index this document after the product is created or updated.
A common architecture is:
Database Transaction
|
v
Application Event
|
v
Background Job
|
v
OpenSearch IndexUsing a background job prevents search indexing from unnecessarily slowing down the user's request.
Handle Search Indexing Failures
The database and search index can temporarily become inconsistent.
For example:
Database update
|
v
Successful
OpenSearch update
|
v
FailedThe application should have a recovery strategy.
Possible approaches include:
Retry queues
Dead-letter queues
Periodic reconciliation
Reindexing jobs
Event-based indexing
Change tracking
Do not assume that one successful indexing request means the systems will remain synchronized forever.
Design for Idempotent Indexing
An indexing operation should ideally be safe to repeat.
For example, use a stable document identifier:
Product ID 101
|
v
OpenSearch document ID 101If the indexing job runs twice, the second operation should update the same document rather than create an unintended duplicate.
This becomes particularly important when background jobs are retried.
Use Bulk Indexing for Large Data Sets
Indexing records individually can create unnecessary network overhead.
For initial data loads or large synchronization jobs, use bulk operations.
Conceptually:
Product 1 ─┐
Product 2 ─┤
Product 3 ─┼──> Bulk Request ──> OpenSearch
Product 4 ─┤
Product 5 ─┘Bulk indexing can significantly reduce request overhead.
However, inspect individual item failures in the bulk response.
A successful HTTP response does not necessarily mean every document was indexed successfully.
Build Search Queries Around User Intent
A search box usually needs more than a simple exact match.
For example:
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "wireless keyboard",
"fields": [
"name^3",
"description"
]
}
}
],
"filter": [
{
"term": {
"category": "accessories"
}
}
]
}
}
}This separates relevance-oriented searching from exact filtering.
The field weighting can help important fields contribute more strongly to ranking.
Do not increase boosts blindly. Validate the resulting search quality with real queries.
Add Pagination
Search results should not return thousands of documents in a single response.
A simple request might use:
{
"from": 0,
"size": 20,
"query": {
"match": {
"name": "keyboard"
}
}
}For large result sets, consider search pagination approaches appropriate for your OpenSearch version and workload.
The application should also impose a maximum page size.
For example:
Requested size: 5000
Allowed maximum: 100
Actual size: 100Never allow clients to control resource-heavy search parameters without limits.
Add Filters and Facets
Application search often requires filters such as:
Category
Brand
Price range
Availability
Location
Date
Status
For example:
{
"query": {
"bool": {
"must": {
"match": {
"name": "laptop"
}
},
"filter": [
{
"term": {
"brand": "ExampleBrand"
}
}
]
}
}
}Filters should be based on appropriately mapped fields.
Do not use full-text fields for exact filters when a keyword-style field is more appropriate.
Protect the OpenSearch Cluster
A self-managed cluster should not be exposed directly to the public internet unless there is a very specific and carefully designed reason.
A safer architecture is:
Internet
|
v
Application API
|
v
Private Network
|
v
OpenSearchApply:
Authentication
Authorization
TLS
Network restrictions
Least-privilege credentials
Secret management
Firewall rules
Application users should generally not receive direct OpenSearch credentials.
Separate Application and Administrative Access
The application does not need administrative permissions.
Create separate access levels for:
Application
-> Search and document operations required by the application
Operations
-> Cluster and index administration
Monitoring
-> Read-only metrics and health informationThis limits the impact of compromised application credentials.
Monitor the Cluster
Self-managed OpenSearch requires operational monitoring.
At minimum, monitor:
CPU
Memory
JVM usage
Disk usage
Search latency
Indexing latency
Request rate
Error rate
Cluster health
Shard status
Unassigned shards
Storage growth
A search cluster can remain technically available while gradually becoming unhealthy because of storage pressure or resource exhaustion.
Monitoring should detect these conditions before users experience failures.
Plan Capacity Before Production
Do not size a production cluster only by the current document count.
Consider:
Documents
+
Document size
+
Index overhead
+
Replicas
+
Query traffic
+
Indexing traffic
+
Growth
=
Required capacityAlso account for operational overhead.
A cluster that has enough disk space today may not have enough capacity after several months of growth.
Configure Replicas Carefully
Replicas can improve availability and distribute search workload.
For example:
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}The appropriate values depend on cluster size and workload.
Do not create a large number of shards simply because the cluster has multiple nodes.
Too many small shards can create unnecessary overhead.
Plan Backups and Recovery
Search indexes should not be treated as disposable unless the application has a reliable way to rebuild them.
Define:
Backup frequency
Retention period
Recovery procedure
Recovery testing
Index rebuild process
Required recovery time
A backup strategy is incomplete until restoration has been tested.
For applications where the relational database is the source of truth, a full reindexing process can also provide an important recovery path.
Handle Search Downtime Gracefully
Search should not always be allowed to take down the entire application.
For example:
OpenSearch available
|
v
Normal search
OpenSearch unavailable
|
v
Fallback behavior
|
v
Application remains usableDepending on the application, fallback behavior might include:
Showing recent results
Using database search for limited cases
Returning a controlled error
Disabling advanced filters temporarily
The right fallback depends on the business requirements.
Common Mistakes
Treating OpenSearch Like a Database
OpenSearch is optimized for search and analytics workloads, not as a replacement for every transactional database feature.
Exposing OpenSearch Directly to Users
Keep cluster access behind controlled application services.
Using the Same Credentials Everywhere
Separate application, administrative, and monitoring access.
Ignoring Indexing Failures
Build retry and reconciliation mechanisms.
Returning Large Search Results
Use pagination and enforce maximum page sizes.
Creating Too Many Shards
Shard counts should be based on actual data and workload requirements.
Skipping Recovery Testing
A backup that has never been restored should not be considered a proven recovery strategy.
Troubleshooting Common Problems
Search Returns No Results
Check:
Index name
Field mapping
Analyzer configuration
Query field
Filter values
Document indexing status
Search Results Are Poor
Review:
Analyzer configuration
Field boosts
Query structure
Synonyms
Stop words
Search test cases
Do not immediately change the ranking formula. First determine whether the documents are being analyzed and indexed as expected.
Indexing Is Slow
Check:
Bulk batch size
Network latency
Refresh behavior
CPU
Memory
Disk performance
Document size
Cluster Becomes Unhealthy
Inspect:
Disk utilization
Shard allocation
Node availability
JVM memory
Recent indexing spikes
Failed operations
Do not simply add nodes without identifying the underlying bottleneck.
Best Practices
Keep OpenSearch Behind an Application Boundary
Centralize search logic in a service or repository layer.
Treat the Database as the Source of Truth
Use OpenSearch as the searchable representation unless the architecture intentionally requires otherwise.
Make Indexing Idempotent
Stable document identifiers make retries safer.
Use Background Processing
Do not make every user request wait for search indexing.
Test Search Relevance
Functional correctness is not enough. Validate the quality of returned results.
Monitor Before Problems Become Incidents
Track cluster health, resource utilization, search latency, and indexing failures continuously.
Plan for Reindexing
Mappings and analyzers can change. A reliable reindexing process makes future improvements easier.
Advantages of Self-Managed OpenSearch
A self-managed OpenSearch deployment provides:
Control over infrastructure
Control over configuration
Flexible deployment options
Custom capacity planning
Potentially predictable infrastructure costs
Ability to integrate with existing operational systems
Greater control over data placement
It can be especially useful for teams that already operate containerized or stateful infrastructure.
Disadvantages and Considerations
The main cost is operational responsibility.
Your team may need to manage:
Cluster upgrades
Security
Backups
Monitoring
Capacity planning
Storage
Shard allocation
Node failures
Recovery
Search performance
Index lifecycle management
A managed service can reduce some of this operational burden.
Therefore, the right comparison is not simply infrastructure cost versus software cost. Include engineering and operational effort in the decision.
When Self-Managed OpenSearch Is a Good Fit
Self-managed OpenSearch can make sense when:
The team has infrastructure expertise
Search is a core application capability
The workload requires custom configuration
Data placement requirements favor direct control
Existing infrastructure can host stateful services
The team is prepared to operate the cluster
A managed solution may be preferable when the organization wants to minimize operational responsibility.
Summary
OpenSearch can provide a strong search platform without relying on a managed Elasticsearch service, but self-management changes the responsibilities of the development and operations teams.
Start with a clear separation between application data and search data. Build a controlled search service, define explicit index mappings, use background indexing, make indexing idempotent, and protect the OpenSearch cluster behind appropriate network and authorization boundaries.
For production, capacity planning, monitoring, backups, shard management, security, and recovery should be treated as part of the application architecture rather than afterthoughts.
The key decision is not whether OpenSearch can perform application search. It can. The more important question is whether your team is prepared to operate the search infrastructure reliably at the scale and availability your application requires.


Join the conversation! Your thoughts help the community grow.