The Best Elasticsearch Hosting Platforms in 2026
Elasticsearch is a distributed Lucene index wearing a JSON API, and almost every hard thing about hosting it comes from that first word. A single node is easy and genuinely useful. The moment you have three, you own a consensus protocol, a shard allocator, a JVM heap that behaves badly if you size it wrong, and a disk watermark that will quietly stop accepting writes rather than page you. This list is a set of answers to who has to care about that.
I'm Ajay, I build PandaStack, and the conflict of interest goes up front: we do not offer managed Elasticsearch or OpenSearch. We run managed PostgreSQL 16 and we host applications, so there is no version of this post where the answer is us. What we host is the other half of a search stack — the API that queries the cluster, the sync worker that keeps it current, the reindex job after a mapping change. The cluster belongs somewhere built for stateful, memory-hungry, heap-tuned JVM services.
The license fork, and why it still shapes the decision
You cannot shop for Elasticsearch hosting without running into the fork. In 2021 Elastic moved Elasticsearch off Apache 2.0 to a dual SSPL / Elastic License model, source-available rather than OSI-approved open source; AWS forked the last Apache-licensed release as OpenSearch. In 2024 Elastic added AGPLv3 as a third option, and separately OpenSearch moved under the Linux Foundation as the OpenSearch Software Foundation. Licensing terms change, so verify the license of the exact version you plan to deploy rather than trusting a blog post — including this one.
The practical consequence is that you are choosing between two codebases that were identical a few years ago and have diverged ever since. Elasticsearch kept moving on vector search and machine learning; OpenSearch built its own vector engine and security plugins. The APIs still rhyme but are not drop-in equivalents at the edges, and the client libraries have split — pointing an official Elasticsearch client at an OpenSearch cluster is unsupported, and the version handshake will tell you so.
What actually drives the cost
Search clusters are priced on nodes and storage but sized by memory, and that gap is where budgets go wrong. Lucene wants two things at once: a JVM heap for the cluster's bookkeeping, and free RAM for the OS page cache, because segment files are memory-mapped and that cache is what makes queries fast. The long-standing guidance is to give the JVM about half the machine's RAM and leave the rest alone.
The other half of that rule is the famous ceiling: keep the heap under roughly 31GB. Below a threshold in that neighbourhood the JVM uses compressed ordinary object pointers, storing references in 32 bits instead of 64. Cross it and every reference gets wider, so a 33GB heap can hold less useful data than a 30GB one. It is a well-established guideline rather than a hard constant — the cutoff depends on the JVM and its flags — but it has held for over a decade. If you need more heap, the answer is more nodes, not a bigger one.
Storage then multiplies. A primary shard with one replica is two copies of your data, and that is the right default — a replica is how you survive losing a node and how you serve concurrent reads. So the disk line on any quote is at least double your raw index size, before accounting for the index being larger than the source documents: Lucene stores an inverted index, doc values, and by default a copy of the original JSON. Snapshots sit on top, with a separate bill.
Which is why tiering is the biggest lever on a large cluster's cost. Hot nodes take writes and serve recent queries on fast local disk; warm nodes hold older indices read occasionally; cold and frozen tiers back indices with object storage, trading latency for a fraction of NVMe prices. For time-series data — logs, events, anything with a date in the index name — a lifecycle policy is worth more than any amount of query tuning. For a product catalogue queried uniformly, tiering buys nothing but complexity.
A single node run by hand makes the sizing concrete:
# Single-node Elasticsearch for local dev or a small production instance.
# Heap is set explicitly: half of RAM, well under the ~31GB compressed-oops
# ceiling. Xms and Xmx MUST be equal -- a growing heap is a stalling heap.
docker run -d --name es \
-p 9200:9200 \
-e discovery.type=single-node \
-e ES_JAVA_OPTS="-Xms8g -Xmx8g" \
-e xpack.security.enabled=true \
--ulimit memlock=-1:-1 \
--ulimit nofile=65536:65536 \
-v es-data:/usr/share/elasticsearch/data \
docker.elastic.co/elasticsearch/elasticsearch:CHECK_CURRENT_VERSION
# Host prerequisites people forget until the container refuses to start:
sudo sysctl -w vm.max_map_count=262144 # Lucene mmaps a lot of files
sudo swapoff -a # a swapped heap is a dead cluster
# The three checks worth wiring into monitoring on day one.
curl -su elastic:"$ES_PASSWORD" localhost:9200/_cluster/health?pretty
curl -su elastic:"$ES_PASSWORD" localhost:9200/_cat/shards?v'&'h=index,shard,prirep,state,unassigned.reason
curl -su elastic:"$ES_PASSWORD" localhost:9200/_cat/allocation?v # disk headroom per nodeWhat 'managed' actually buys you
Version upgrades. Both engines upgrade across one major version at a time, and each major has removed mappings, deprecated query syntax and breaking client changes. A rolling upgrade is a real project with a rollback plan, and because you cannot skip majors, falling behind gets worse rather than better.
Snapshot lifecycle. Both engines write incremental backups to object storage, with a policy mechanism to run it on a schedule with retention. Setting that up yourself is an afternoon. Discovering it silently stopped working four months ago is a different kind of afternoon.
And the one people actually pay for: shard rebalancing at 3am. When a node dies the cluster promotes replicas to primaries and copies data to restore the replica count, competing for the same disk and network as live traffic. Getting that right means allocation awareness, recovery throttling so the rebuild does not starve queries, and disk headroom on the survivors. A managed service has a runbook and a rotation for this. You have a laptop and a bad feeling.
Nobody's search cluster fails at 2pm on a Tuesday when the person who set it up is at their desk. It fails at 3am, and it fails by filling a disk.
The options
1. Elastic Cloud
First-party managed Elasticsearch on AWS, GCP or Azure, run by the company that writes it. It is the reference implementation: hot/warm/cold/frozen tiering with searchable snapshots against object storage, index lifecycle management wired in, Kibana alongside, and newer vector search and ML features the day they ship rather than whenever a fork catches up.
Choose it for the full Elastic surface, or if you already run the wider stack. Look elsewhere if the licensing model matters to you legally, if data must stay in your own cloud account, or if the bill at your scale beats the convenience. Check where the boundary between included and paid-tier features currently sits — it has moved more than once.
2. Amazon OpenSearch Service
AWS's managed OpenSearch, and for many teams the path of least resistance, because the integration story is the product: IAM-based access control instead of a separate credential store, VPC-only endpoints, CloudWatch and Firehose delivering straight into it, and a serverless variant that separates indexing from search compute. For log analytics over AWS-generated data, that alone is hard to beat.
Two things to check. On provisioned domains, configuration changes run as blue/green deployments, so an edit takes a long time and consumes cluster resources while it runs. And the serverless flavour has a different feature surface and pricing unit — evaluate the one you will actually run.
3. Self-hosted on plain VMs
The most underrated option, and the one people talk themselves out of too quickly. One node with good NVMe, a sane heap and a snapshot policy pointed at object storage carries a very large number of applications — product search over a few million documents is not a distributed systems problem, it is one machine with enough RAM to hold the index in page cache. Past one node, run three master-eligible ones so the cluster forms an unambiguous majority. You own the upgrades, the snapshot verification and the 3am recovery. It stops being reasonable when you need tiers or multi-AZ allocation awareness — or when the person who set it up leaves. The cost is not the servers; it is the knowledge living in one head.
4. Kubernetes with ECK or the OpenSearch operator
Elastic Cloud on Kubernetes is Elastic's official operator; the OpenSearch project has its own. Both make topology declarative — node roles, storage classes, resource limits, TLS, rolling upgrades — and both fit if you already run Kubernetes seriously. The trap is thinking an operator removes the operations. It removes toil, not responsibility: you still choose heap, shard counts, storage class and anti-affinity rules, and you have added a StatefulSet with persistent volumes to the things that make cluster upgrades interesting. Excellent with a platform team, a poor idea if you would adopt Kubernetes in order to run search. Read ECK's licensing terms first.
5. Bonsai
A long-running independent specialist hosting both engines, doing exactly this and only this for years. The pitch is not the biggest feature matrix; it is that someone who knows search answers your support ticket. For a mid-sized team whose cluster is important but is not the product, that is a good trade. It fits application search — Rails and Django shops with search-as-a-feature — better than petabyte log analytics. Verify which versions and plugins they support: the smaller specialists are deliberately conservative about the plugin surface.
6. The broader managed field (Aiven, Instaclustr, cloud marketplaces)
A category rather than a product: vendors running OpenSearch as one service among many. Aiven runs it beside Kafka, Postgres and ClickHouse, which is convenient when your index is fed by a Kafka topic and you want one bill for the pipeline. Instaclustr sits in similar territory with strong open-source-only positioning. Pick from this tier when search is one component of a data platform you are buying wholesale. Check which fork they run, whose cloud account it lands in, and their upgrade cadence.
7. PandaStack — the application side, not the cluster
Stated plainly, once: we are not an Elasticsearch host. No managed Elasticsearch, no managed OpenSearch, no plans for either — if you need a cluster, buy one from somebody above. What we run is the code around it. A PandaStack app is a full Ubuntu userspace in a Firecracker microVM with its own guest kernel under KVM, deployed from git, so the search API, the sync worker tailing your database into the index, and the reindex job are ordinary Linux processes.
That division matters because of workload shape. The cluster runs continuously; it is stateful and holds your index in RAM. The indexer does not — a reindex is a burst after a schema change and then it stops, and a nightly sync job is idle twenty-three and a half hours a day. Ours scale to zero, and a sandbox restores from a snapshot with a p50 around 179ms and a p99 around 203ms, so the job that reindexes twice a week needs no permanent node.
# The indexer side: a reindex is a burst, not a resident service.
# Spin a microVM, run the job, throw the machine away.
from pandastack import Sandbox
sbx = Sandbox.create(template="base", ttl_seconds=1800)
r = sbx.exec("python reindex.py --since 2026-09-01")
sbx.destroy()
print(r.exit_code, r.stdout[-2000:])The other honest overlap is managed Postgres 16, which matters for the reason in the next section: a meaningful share of teams shopping for a search cluster do not need one. A database takes 30–90 seconds to create and ships with pgvector.
Side by side
- Elastic Cloud — Model: first-party managed Elasticsearch, full tiering, ILM and Kibana. Ops: none. Best for: the complete Elastic feature surface first. Watch: licensing, and the paid-tier boundary.
- Amazon OpenSearch Service — Model: managed OpenSearch, IAM auth, VPC endpoints, plus a serverless variant. Ops: none, but config changes are slow blue/green deployments. Best for: AWS-native log analytics. Watch: serverless and provisioned are different products.
- Self-hosted on VMs — Model: one to three nodes you install, tune and snapshot yourself. Ops: all of it, including the 3am recovery. Best for: application search where one machine suffices. Watch: knowledge living in one person's head.
- Kubernetes with ECK or the OpenSearch operator — Model: declarative topology in your own infrastructure. Ops: toil automated, decisions not. Best for: organisations with a platform team. Watch: operator licensing, and StatefulSets complicating upgrades.
- Bonsai — Model: independent specialist hosting both engines, with search-literate support. Ops: none. Best for: mid-sized application search that is not itself the product. Watch: supported versions and plugin surface.
- Aiven, Instaclustr and similar — Model: OpenSearch inside a broader managed data platform. Ops: none. Best for: buying the queue, the database and the index from one vendor. Watch: which fork, whose account, upgrade cadence.
- PandaStack — Model: not a search host. Firecracker microVMs running the API, sync worker and reindex jobs that talk to your cluster, plus managed Postgres 16 with pgvector. Ops: yours, but they scale to zero. Best for: the bursty indexer tier.
When not to use Elasticsearch at all
The most expensive search architecture is the one you did not need. A surprising share of 'we need search' requirements are satisfied by Postgres, which has had full-text search built in for a long time and is good at it: a tsvector column, a GIN index, ts_rank for ranking, trigram similarity for typo tolerance. One database instead of two, one backup instead of two, and no eventually-consistent copy that can silently drift.
-- Postgres full-text search: a generated tsvector plus a GIN index.
-- Weights let a title match outrank a body match, which is most of what
-- people actually want from "relevance".
ALTER TABLE articles ADD COLUMN search_doc tsvector
GENERATED ALWAYS AS (
setweight(to_tsvector('english', coalesce(title, '')), 'A') ||
setweight(to_tsvector('english', coalesce(body, '')), 'B')
) STORED;
CREATE INDEX articles_search_idx ON articles USING GIN (search_doc);
-- Fuzzy matching and typo tolerance, without a second database engine.
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX articles_title_trgm ON articles USING GIN (title gin_trgm_ops);
SELECT id, title, ts_rank(search_doc, q) AS rank
FROM articles, websearch_to_tsquery('english', 'firecracker microvm') AS q
WHERE search_doc @@ q
ORDER BY rank DESC
LIMIT 20;
-- Always EXPLAIN ANALYZE this on production-sized data. A GIN index the
-- planner never chooses is just a slower INSERT.The same logic applies to semantic search. pgvector stores embeddings in Postgres and indexes them with HNSW, covering the retrieval half of most RAG systems, and combining it with the tsvector column above gives hybrid keyword-plus-semantic search in one query. For a corpus in the low millions of rows that is not a compromise; it is the simpler architecture that also happens to be correct.
Elasticsearch earns its place when you need what Postgres does not do well: query-time aggregations over large document sets, faceted navigation across many fields, per-field analyzers and language-specific stemming, relevance tuning as an ongoing activity, or ingest volumes where the write path must be separate from your transactional database. If your requirement is a LIKE clause and a product manager who said the word 'search', start with the database you have.
Four traps that will find you
- Unassigned shards. Yellow means replicas are unassigned; red means a primary is. The cause is almost always disk, allocation filtering, or a node that left and took a shard copy with it. The cluster allocation explain API gives the exact reason — run it first, not last. It turns a 3am guessing game into a sentence.
- Split brain. Old versions could form two clusters that both believed they were in charge, producing diverging data rather than an error. Modern versions replaced minimum-master-nodes with a proper voting configuration, but the lesson stands: run an odd number of master-eligible nodes.
- Mapping explosions. Dynamic mapping is convenient until you index user-supplied JSON, at which point every distinct key becomes a field and cluster state grows without bound — and that state is replicated to every node. Disable dynamic mapping on any index fed by data you do not control, or use a flattened field type so an arbitrary object is one field, not hundreds.
- The flood-stage watermark. When a node's disk crosses the threshold, Elasticsearch applies a read-only-allow-delete block to the affected indices. It is a safety feature doing exactly what it should, and also the most confusing failure mode in the product: writes fail while the cluster reports itself green. Clearing it means freeing disk and then explicitly removing the block. Alert on per-node disk headroom, not cluster health.
How to choose in ten minutes
- Establish whether you need a search engine at all. Write down document count, query shapes, and whether anyone will actually tune relevance. If the answer is 'a few million rows and a text match', try a tsvector column and a GIN index first — it costs an afternoon and often ends the project.
- Pick the fork before the vendor. Elasticsearch or OpenSearch determines your clients, your plugins and most of your shortlist. Decide deliberately rather than inheriting it from whichever pricing page you opened first.
- Size on memory, not nodes. Index size drives page cache, page cache drives RAM, and the heap is half of it with a ceiling around 31GB. Then double the storage figure for replicas and add snapshots.
- Decide whether your data is time-series or uniform. Time-series makes tiering the biggest cost lever available; uniform data makes it complexity you should not buy.
- Separate the cluster decision from the indexer decision. The cluster is stateful and continuous; the sync worker and reindex job are bursty and can scale to zero somewhere cheaper. Sizing a permanent node for a job that runs twice a week is avoidable.
The short version
Elastic Cloud for the first-party feature set. Amazon OpenSearch Service if your data already flows through AWS. Self-hosted VMs if this is application search and you will own the recovery. ECK if you already run Kubernetes as a platform. Bonsai if you want a specialist who answers the phone. Aiven or Instaclustr if the index is one part of a data platform you are buying whole.
Before any of that, check whether Postgres already does what you need — the cheapest search cluster is the one that turned out to be a GIN index. If you do buy one, remember the division of labour: the cluster is a stateful JVM service that wants a specialist host, and the indexing tier around it is ordinary code that should not pay for idle nodes. That second half is what we run, and I would rather say so straight than pretend our microVMs have opinions about your heap.
Frequently asked questions
Should I use Elasticsearch or OpenSearch in 2026?
It mostly comes down to licensing preference and hosting fit. Elasticsearch is developed by Elastic under a dual source-available model that added AGPLv3 as an option in 2024; OpenSearch is the AWS-originated Apache 2.0 fork that moved under the Linux Foundation. Verify the current license of the exact version you plan to run rather than trusting any summary. Practically: choose Elasticsearch if you want Elastic's newest features and Elastic Cloud, choose OpenSearch if you want Apache licensing or you are deep in AWS. The two codebases have diverged enough that client libraries are no longer interchangeable, so decide before you write integration code.
How much heap should I give Elasticsearch?
The long-standing guidance is roughly half the machine's RAM, with the rest left free for the operating system page cache, because Lucene memory-maps its segment files and the page cache is what makes queries fast. Set Xms and Xmx to the same value so the heap does not grow at runtime. Keep the heap under approximately 31GB: below a threshold in that neighbourhood the JVM uses compressed ordinary object pointers, so references cost 32 bits instead of 64, and crossing it can mean a larger heap holds less useful data. If you need more heap than that ceiling allows, add nodes rather than growing one.
Can Postgres replace Elasticsearch for search?
For a lot of workloads, yes. Postgres full-text search with a generated tsvector column, a GIN index and ts_rank for ranking handles keyword search over corpora in the low millions of rows well, and pg_trgm adds fuzzy matching and typo tolerance. pgvector covers semantic search and the retrieval half of most RAG systems, and you can combine both for hybrid search in one query. That means one database, one backup and one consistency model instead of an eventually-consistent index that can drift. Elasticsearch earns its place when you need query-time aggregations over large document sets, faceted navigation, per-language analyzer pipelines, or relevance tuning as an ongoing activity.
Why did my Elasticsearch cluster become read-only?
Almost certainly the flood-stage disk watermark. When a data node's disk usage crosses the flood-stage threshold, Elasticsearch applies a read-only-allow-delete block to indices with shards on that node, so writes are rejected while the cluster may still report itself green. It is a safety mechanism preventing a full disk from corrupting the node, but it is genuinely confusing because health checks look fine while every write fails. The fix is to free disk space and then explicitly remove the index block, since it does not always clear itself immediately. Alert on per-node disk headroom rather than relying on cluster health status.
Does PandaStack offer managed Elasticsearch?
No. We run managed PostgreSQL 16 and host applications on Firecracker microVMs; we do not offer managed Elasticsearch or OpenSearch, and a search cluster should be bought from a provider built for stateful, heap-tuned JVM clusters. What we host well is the tier around it: the search API, the sync worker that pushes database changes into the index, and the reindex job that runs after a mapping change. Those are bursty rather than continuous, and our apps and sandboxes scale to zero, with snapshot-restore giving a create around 179ms at p50. If your search need turns out to be a tsvector or pgvector query, our managed Postgres does cover that.
Keep reading
- The best vector database hosting platforms in 2026 — The semantic half of the same decision.
- How to add pgvector to a Postgres database — When the search you need is embeddings, not Lucene.
- Isolating per-tenant search indexing — Running untrusted indexing jobs without shared blast radius.
- The best managed Postgres providers in 2026 — The database that often makes the cluster unnecessary.
- Running background workers alongside web apps — Where the sync worker and reindex job belong.
- Managed Postgres on PandaStack — tsvector, pg_trgm and pgvector in one instance.
49ms p50 cold start. Fork, snapshot, and scale to zero.