Multi-Tenancy in Elasticsearch: Sharing One Search Engine Without Sharing Your Secrets
A deep, plain-English guide to serving many customers from one Elasticsearch platform: the three isolation models, the hidden costs of each, and the security, performance and lifecycle rules that keep every tenant safe and fast.
Imagine you own a big apartment building. Every family inside wants a front door with its own lock, a private kitchen, and peace and quiet. But you cannot afford to build a separate building for every family. So you share the plumbing, the roof, the elevator and the electricity, while giving each family walls and keys that keep their lives apart. Multi-tenancy in Elasticsearch is exactly that puzzle: how do you let hundreds or thousands of customers share one search platform, so it stays affordable, while making sure nobody can peek into a neighbor’s flat, hog the elevator, or flood the hallway?
1What Multi-Tenancy Means and Why Elasticsearch Makes It Tricky
Before choosing a design, you need a crisp picture of the problem you are solving.
Defining a tenant
A tenant is a customer, team, or organization that uses your system and expects its data to be treated as private and its experience to be consistent. In a company that sells software to other companies, each paying customer is usually a tenant. In an internal platform, each department or product team may be a tenant. Multi-tenancy simply means that one running system serves many tenants at the same time, instead of running a separate copy of the system for each one.
The word tenant is about a relationship, not a technology. A tenant might have three users or three million. It might store ten documents or ten billion. Any good design has to survive both extremes, because in real businesses the size of your customers follows a steep curve: a few giants and a very long tail of small ones.
Think of a shared office building. Each company rents a floor and has its own badge system, but they all share the lobby, the water pipes and the fire alarm. A leaking pipe on one floor can annoy everyone. That is multi-tenancy: shared infrastructure, private spaces, and the constant need to stop one tenant’s problems from becoming everyone’s problems.
Why do teams choose multi-tenancy at all?
The answer is almost always cost and operations. Running a dedicated search cluster per customer means paying for idle capacity many times over, patching many clusters, upgrading many clusters and watching many dashboards. Sharing infrastructure lets you pack many small workloads onto the same machines, keep hardware busy, and operate one fleet rather than thousands of tiny ones. The price you pay is complexity in isolation, security and fairness.
The three promises every tenant expects
Data isolation
Tenant A must never see, count, or even infer the existence of Tenant B’s documents.
Performance isolation
A heavy query or a huge import from one tenant must not make everyone else slow.
Operational isolation
Onboarding, deleting, restoring or migrating one tenant should not disturb the rest.
Cost fairness
Every tenant should pay roughly what it consumes, and you should be able to measure that.
Why Elasticsearch is a special case
In a traditional relational database, you can often add a tenant identifier column and lean on mature row-level security. Elasticsearch is different in several ways that matter for design. It is a distributed system built from many small pieces called shards, and every piece has a fixed overhead. Its cluster-wide metadata is held in memory on every node. Its search results are ranked using statistics that are computed across all documents in a shard, so tenants sharing a shard subtly influence each other’s relevance. And its most powerful isolation features, such as document-level security, belong to paid subscription tiers rather than the free core.
These traits mean that the obvious choices, one index per tenant or one big shared index, each have a cliff waiting at the end. The whole art of multi-tenancy in Elasticsearch is knowing where those cliffs are before you walk off them.
Many people believe that adding a tenant field to every document and filtering on it is “secure enough”. A filter is only as safe as the code that remembers to add it. One forgotten filter in one service is a data breach. Real isolation is enforced by the platform, not by good intentions.
2Elasticsearch Foundations You Need First
Every multi-tenancy decision is really a decision about these basic building blocks.
If you already know these terms, skim this chapter. If not, read it slowly, because every later chapter leans on it. We will define each idea in plain words, give an everyday comparison, and say why it matters for tenants.
Cluster
A group of machines working together as one search system, with one shared set of metadata.
Node
One running Elasticsearch process. Nodes can play roles such as master, data, ingest or coordinating.
Index
A named collection of documents with a shared structure, like a labeled filing cabinet.
Shard
A slice of an index. Each shard is a complete, self-contained search engine in miniature.
Replica
A copy of a shard kept on another node for safety and extra read capacity.
Mapping
The blueprint that says which fields exist and what type each one is, such as text, number or date.
Alias
A friendly nickname that points at one or more indices, optionally with a built-in filter.
Segment
An immutable chunk of data inside a shard. Segments are merged in the background over time.
Index, shard and replica in one picture
When you create an index you decide how many primary shards it has. That number is essentially fixed for the life of the index, because documents are placed into shards using a formula based on the document identifier or a routing value. You can later use special split or shrink operations to change it, but they are deliberate, heavy operations rather than casual settings.
Each primary shard can have replica copies. If a node dies, a replica is promoted, so no data is lost. Replicas also help read traffic, because a search can be answered by either a primary or a replica.
An index is a library. Shards are the bookshelves the library is split across, so that many librarians can search different shelves at once. Replicas are photocopies of each shelf stored in another room, so a flooded room does not destroy the collection.
Why shards have a “tax”
Every shard, even an empty one, costs memory, file handles and cluster coordination effort. Elasticsearch keeps information about every shard in the cluster state, and every node holds a copy of that state. Two guardrails are worth remembering. First, there is a configurable limit on shards per node, which defaults to one thousand for regular data nodes. Second, a commonly quoted rule of thumb sizes shards between roughly ten and fifty gigabytes each, so that they are large enough to be efficient but small enough to move around and recover quickly. Always check the current official guidance for your version, since these recommendations have evolved.
This shard tax is the single most important fact in multi-tenant design. If you give every tenant its own index with the default shard settings, ten thousand tenants can quietly become tens of thousands of tiny shards, and your cluster will spend its life bookkeeping instead of searching.
Mappings and the field budget
A mapping lists the fields of your documents. By default, Elasticsearch will happily add new fields on the fly when it sees them, a behavior called dynamic mapping. There is also a default cap on the total number of fields in an index, which is one thousand. When tenants are allowed to send arbitrary fields, mappings can grow without bound. We will return to this danger in a later chapter under the name mapping explosion.
Three budgets constrain every multi-tenant design: the number of shards, the number of fields, and the amount of shared compute for searching and indexing. Each isolation model spends these budgets differently.
3The Tenancy Spectrum: Silo, Pool and Bridge
Multi-tenancy is not one design. It is a dial that runs from “nothing shared” to “everything shared”.
Architects who build software-as-a-service platforms usually describe three broad patterns. The names come from general cloud architecture, and they map neatly onto Elasticsearch.
Silo: every tenant gets its own dedicated stack
In Elasticsearch terms this is a separate cluster or hosted deployment per tenant. Isolation is the strongest possible, and so is the cost.
Pool: everyone shares the same resources
Here many tenants live inside the same indices, separated only by a tenant identifier field, routing, filtered aliases and security rules. Cost is the lowest, and the isolation burden falls on your design.
Bridge: a deliberate mixture
Some parts are shared and some are dedicated. The most common Elasticsearch bridge is an index per tenant on a shared cluster, or pooled indices for small tenants and dedicated indices or clusters for large ones.
flowchart LR
A["Silo: cluster per tenant"] --> B["Bridge: index per tenant on shared cluster"]
B --> C["Bridge: pooled small tenants plus dedicated large tenants"]
C --> D["Pool: shared index with tenant field, routing and filtered alias"]
A -. "Strongest isolation, highest cost" .-> A
D -. "Lowest cost, most design effort" .-> D
How to choose: the four questions
Instead of asking “which model is best”, ask four questions about your situation. How many tenants will you have, and how skewed is their size? How strict are your compliance and contractual isolation requirements? How different are your tenants’ data shapes and search needs? And how much operational effort can your team afford?
| Question | Points toward Silo | Points toward Pool |
|---|---|---|
| Number of tenants | Tens, each large | Thousands, mostly small |
| Compliance rules | Regulated, contractual physical separation | Logical separation is acceptable |
| Schema variety | Each tenant has custom fields and analyzers | All tenants share one schema |
| Operational capacity | Automation for many clusters exists | Small team, one fleet |
| Revenue per tenant | High, can fund dedicated resources | Low, must share to be profitable |
Silo is a detached house for each family. Pool is a hostel dormitory with lockers. Bridge is a residential tower with private apartments but shared utilities, and maybe a few penthouses for the wealthiest residents. Most successful platforms end up as towers, not as pure houses or pure dormitories.
4Model One: An Index for Every Tenant
The most intuitive design, and the easiest to explain to a security auditor.
How it works
In this model each tenant owns one or more indices whose names contain the tenant identifier. Your application routes each request to that tenant’s index, or to an alias that points to it. Because an index is a first-class object in Elasticsearch, everything you might want to control, such as settings, mappings, analyzers, shard counts, retention and access rules, can be set per tenant without touching anyone else.
Each tenant gets their own filing cabinet in a shared records room. The room, the lights and the security guard are shared, but no drawer is ever mixed with another’s.
What you gain
Advantages
- Clean data isolation that is simple to reason about and to audit
- Per-tenant mappings, analyzers, synonyms and settings are trivial
- Deleting a tenant is nearly instant, because dropping an index removes files rather than marking documents
- Access control by index name pattern is straightforward and does not depend on document filters
- Big tenants can be given more shards and replicas, or pinned to specific nodes
- Per-tenant backup and restore through snapshots is natural
Disadvantages / Trade-offs
- Every index costs at least one shard, so tenant count directly multiplies shard count
- Cluster state grows with every index and every mapping, slowing master operations
- Thousands of tiny shards waste memory and reduce search efficiency
- Searching across tenants, for example for platform analytics, means touching many indices
- Template changes must be rolled out to a very large number of indices
The small-tenant trap
The classic failure story goes like this. A team launches with fifty tenants and one index each, using the default settings. It works beautifully. Two years later there are eight thousand tenants, most of them tiny, and the cluster has crossed into tens of thousands of shards. Cluster state updates take seconds. Node restarts take an hour because shard recovery is a traffic jam. Heap usage is high even though the data volume is modest. Nothing is wrong with any single tenant. The design simply spent the shard budget on customers who did not need a full shard each.
Index-per-tenant is safe to start with, but it has a ceiling that depends on your hardware and version. Decide at design time what your maximum tenant count is, and what you will do when you approach it. Do not discover the ceiling in production.
Ways to stretch the model
Use one primary shard for small tenants
Most small tenants do not need more than one primary shard. Setting the count deliberately low avoids paying a shard tax for capacity that will never be used.
Tune replicas by tier
A free-tier tenant might run with zero or one replica while a premium tenant gets more, trading cost against resilience on purpose.
Manage everything through templates
Index templates apply consistent settings and mappings to every new tenant index automatically, so onboarding is a single, repeatable step.
Move small tenants into a pool
When the tail becomes too long, consolidate the smallest tenants into shared indices, keeping dedicated indices only for the ones that justify them. This leads naturally to the hybrid designs in a later chapter.
5Model Two: Shared Indices with Routing and Filtered Aliases
The pooled design that scales to enormous tenant counts, at the price of more careful engineering.
How it works
In the pooled model, many tenants store their documents in the same index. Every document carries a tenant identifier field. Queries always restrict results to a single tenant. To make this efficient and safe, three Elasticsearch features are combined: a keyword field holding the tenant identifier, custom routing that sends each tenant’s documents to a predictable shard, and filtered aliases that bake the tenant restriction into a named entry point.
Picture one giant warehouse with colored labels on every box. Routing is the rule that says “all red boxes go to aisle 7”, so a worker fetching red boxes only walks down one aisle. A filtered alias is a window that only shows red boxes, so a red-team worker cannot even see the blue ones.
Custom routing: keeping a tenant in a few shards
Normally, Elasticsearch decides which shard a document goes to by hashing its identifier, which spreads documents evenly. A search then has to visit every shard of the index. With custom routing, you supply a routing value, typically the tenant identifier, and Elasticsearch hashes that instead. All of a tenant’s documents land on the same shard, and a search that supplies the same routing value visits only that shard. For a platform with fifty shards per index, that can be a fifty-fold reduction in work per query.
For very large tenants, one shard may not be enough, and it would become a hot spot. Elasticsearch offers a routing partition size setting that spreads each routing value across a small group of shards rather than a single one. This is a middle path: better balance for big tenants, still far fewer shards touched than a full scatter.
flowchart TD
U["Tenant 42 user searches"] --> APP["Application layer"]
APP --> AL["Filtered alias for tenant 42"]
AL --> RT["Routing value: tenant 42"]
RT --> S3["Shard 3 only"]
S3 --> F["Tenant filter applied automatically"]
F --> R["Results for tenant 42 only"]
IDX["Shared index with many shards"] --- S3
Filtered aliases: safety by construction
An alias can be defined with a filter, and optionally with index and search routing values. When your application searches through the alias for tenant 42, Elasticsearch adds the tenant filter and the routing for you. The application does not have to remember anything. Combined with a role that only grants access to that alias, it becomes much harder to accidentally read another tenant’s data, because the caller simply has no name for the shared index.
Creating one alias per tenant is cheap compared with creating one index per tenant, though aliases are still stored in cluster state, so tens of thousands of them can add up. Plan for that number just as you would for indices.
Strengths and weaknesses
Advantages
- Shard count stays small and predictable regardless of tenant count
- Cluster state stays compact, keeping the master healthy
- Adding a tenant is a lightweight operation, often just an alias
- Cross-tenant analytics for the platform owner are simple
- Resources are used very efficiently for a long tail of tiny tenants
Disadvantages / Trade-offs
- All tenants share one mapping, so schema conflicts affect everyone
- Deleting or exporting a tenant means expensive delete-by-query or reindex operations
- Large tenants can create hot shards and skew the cluster
- Relevance statistics are shared per shard, so tenants influence each other’s ranking
- Isolation depends on correct filters, aliases and roles
- Per-tenant custom analyzers and settings are difficult
Mark the routing field as required in the mapping. Then any attempt to index a document without a routing value fails loudly instead of silently scattering a tenant’s data across the index.
6Model Three: Dedicated Clusters and Deployments
The silo: maximum separation, maximum responsibility.
How it works
In the silo model, each tenant receives its own Elasticsearch cluster or its own hosted deployment. Nothing is shared at the search layer: not the shards, not the heap, not the disks, not the master node. Whatever one tenant does, another tenant’s cluster cannot feel it.
This is giving each family its own detached house on its own plot. They never hear each other’s music and cannot possibly borrow each other’s tools. It is wonderful for privacy and terrible for your land budget.
When the silo is the right answer
Regulated industries
Banks, healthcare providers and government bodies often have contracts or regulations that demand physical or account-level separation of data, sometimes in a specific region or cloud account.
Very large or very unpredictable tenants
A tenant whose workload is measured in terabytes and heavy aggregations deserves its own capacity, so that neither it nor its neighbors ever have to compete.
Custom versions and maintenance windows
Some customers want to upgrade on their own schedule, run particular plugins, or use specific configuration. Only dedicated clusters can accommodate that without conflict.
Data residency
If a tenant’s data must remain in one country or region, a cluster placed in that region is the most straightforward guarantee. Cross-cluster search can then let your platform query many regional clusters without moving data.
The operational bill
The catch is that you now run a fleet. Every cluster needs monitoring, patching, backups, capacity planning and incident response. Without heavy automation, the human cost grows linearly with tenant count. Idle capacity also adds up: a cluster sized for peak load sits mostly unused most of the day, and you pay for that many times over.
| Aspect | Index per tenant | Shared index | Cluster per tenant |
|---|---|---|---|
| Data isolation | Strong, logical | Moderate, depends on filters and roles | Strongest, physical |
| Noisy neighbor risk | Moderate | Highest | None between tenants |
| Cost efficiency | Good for medium counts | Best for long tails | Lowest |
| Tenant deletion | Instant | Slow and costly | Delete the cluster |
| Custom schema per tenant | Easy | Hard | Trivial |
| Operational effort | One fleet | One fleet | Many fleets |
| Practical tenant ceiling | Thousands | Very large | Tens to hundreds |
Hosted offerings, such as Elastic Cloud deployments or serverless projects, reduce the operational bill of the silo by automating creation, upgrades and scaling. That can make dedicated-per-tenant economical for far more customers than self-managed clusters would allow.
7Hybrid and Tiered Designs: The Bridge in Practice
Real platforms rarely stay pure. They graduate tenants between models as those tenants grow.
The most durable multi-tenant Elasticsearch platforms treat isolation as a service tier rather than a single decision. The pattern is simple to state: small tenants share, medium tenants get their own indices, and large or regulated tenants get dedicated infrastructure. Your platform then includes a small control layer that knows where each tenant currently lives and can move it.
An airline has economy, business and private charter. Everyone reaches the same destination, but the level of shared space and personal service differs, and so does the price. Passengers can be upgraded when their needs change. Tenant tiers work the same way.
flowchart TD
T["Tenant request"] --> RG["Tenant registry: where does this tenant live?"]
RG -->|"Free or small"| P["Pooled shared indices"]
RG -->|"Growing"| I["Dedicated index on shared cluster"]
RG -->|"Enterprise"| D["Dedicated nodes or dedicated cluster"]
RG -->|"Regulated region"| R["Regional cluster with cross-cluster search"]
The tenant registry
The registry is a small, highly reliable lookup, often kept in a relational database or a configuration store, that maps a tenant identifier to its current home: which cluster, which index or alias, which routing value, and which quota limits. Every request begins by consulting it. Because the application never hard-codes where a tenant lives, you can move tenants without changing any callers.
Using node roles and data tiers
Elasticsearch lets you label nodes with attributes and tell indices which nodes they may live on. You can therefore dedicate a group of nodes to premium tenants inside a shared cluster. This gives you a stronger performance boundary than pure logical sharing, because heavy tenants literally run on different machines, while still keeping one cluster to operate. Separately, the built-in hot, warm, cold and frozen data tiers let older tenant data migrate onto cheaper hardware as it ages.
Start every new tenant in the pool
Onboarding is instant and cheap. The tenant registry records the alias and routing value.
Watch usage against thresholds
Document counts, storage size, query rate and indexing rate are measured per tenant and compared with limits.
Graduate the tenant
When a tenant crosses a threshold, its documents are copied to a dedicated index using reindexing, and the registry is updated once the copy is verified.
Clean up the old location
After a safety period, the tenant’s documents are removed from the shared index, freeing space for others.
Teams often design the pool and the dedicated tier as two unrelated code paths. Build one abstraction, a “tenant search handle”, that hides the difference. Otherwise every feature must be implemented twice and the two paths slowly diverge.
8Inside the Engine: What Happens to a Tenant’s Request
To predict noisy neighbors, you must understand where tenants actually collide.
The life of a search
When a search arrives at any node, that node acts as the coordinating node for the request. It figures out which shards must be consulted, sends the query to one copy of each of those shards, waits for their partial results, merges them into a final ranked list, and then fetches the actual documents for the winners. This two-phase approach is often called query then fetch.
sequenceDiagram
participant C as Client
participant N as Coordinating node
participant S1 as Shard copy A
participant S2 as Shard copy B
C->>N: Search for one tenant
N->>N: Resolve alias, filter and routing
N->>S1: Query phase
N->>S2: Query phase
S1-->>N: Top matches
S2-->>N: Top matches
N->>N: Merge and rank
N->>S1: Fetch phase for winners
S1-->>N: Documents
N-->>C: Final results
The four collision points
Thread pools
Search and write operations run on limited pools of threads. If one tenant fills the queue, others wait behind it.
Memory and caches
Heap, request caches, query caches and field data structures are shared, so a memory-hungry query can evict or starve others.
Disk and merge pressure
Heavy indexing creates many segments, and background merges compete with searches for disk throughput.
Cluster state and master
Creating indices, changing mappings and moving shards all queue up on a single elected master.
Why shards behave like tiny search engines
Each shard is a full Lucene index. Data is written into small immutable segments, and searches read across all segments of a shard. Deletions do not remove data immediately. They mark documents as deleted, and the space is only reclaimed when segments merge. This is the reason tenant deletion inside a shared index is slow: you are marking potentially millions of documents and then waiting for merging to physically remove them.
A segment is like a printed page that cannot be erased. To “delete” a sentence you draw a line through it. Only when the library reprints and combines pages, the merge, does the crossed-out sentence finally disappear.
Where routing helps and where it does not
Routing reduces the number of shards touched by a query, which lowers cost and speeds up small tenants. But it also concentrates a tenant on a few shards. If that tenant is popular, those shards become hot, and the replica copies serving them share the load. Routing therefore improves efficiency for the average tenant and can worsen imbalance for the biggest one, which is why the partition size setting and dedicated indices for giants exist.
Adaptive replica selection lets the coordinating node prefer the shard copy that is currently responding fastest. It softens hot spots automatically, but it cannot create capacity that does not exist.
9Cluster State, Mapping Explosion and the Hidden Cost of Many Indices
The quietest scaling limit is not data volume. It is metadata.
What the cluster state contains
The cluster state is the master copy of the cluster’s structure: which indices exist, their settings and mappings, where every shard lives, which aliases exist, and more. One elected master node changes it, and every change is sent to all other nodes. Every node keeps the whole thing in memory. When the state is small, changes are quick. When it holds tens of thousands of indices with rich mappings, each change can take noticeable time, and the master becomes a bottleneck for anything structural, such as creating a tenant.
The cluster state is the building directory posted in every lobby. With fifty tenants it is one tidy sheet. With fifty thousand it is a phone book that someone must reprint and redistribute every time a single family moves in.
Mapping explosion
Mapping explosion happens when an index accumulates a huge number of distinct fields. It typically starts innocently. A platform lets tenants send custom attributes, dynamic mapping creates a field for each new attribute name, and after a few thousand tenants you have hundreds of thousands of field names in one shared index. Memory use climbs, the cluster state balloons, and updates slow down. Elasticsearch protects you with a total fields limit, but hitting it means new documents are rejected, which is an outage for the tenant who happened to send the last field.
Problem
Tenants are allowed to define their own fields, and each field name becomes a real field in the shared mapping.
Why It’s Harmful
The mapping grows without limit, cluster state becomes huge, and one tenant’s unusual data can block ingestion for all tenants once the field cap is reached.
Correct Approach
Store tenant-defined attributes using a flattened field type or a key-value structure such as a nested list of name and value pairs, and set dynamic mapping to strict for the rest of the document so unknown fields are refused.
Controls that keep metadata healthy
Use strict mappings
Decide the schema deliberately. Reject or divert unknown fields instead of accepting them.
Use flattened fields for free-form data
A flattened field stores an entire object as one mapped field, so tenant-defined keys do not each create a new mapping entry.
Set limits on fields, depth and nesting
Keep the total fields limit modest, and cap depth and nested object counts, so a bad payload fails fast in one place.
Track shard and index counts
Alert well before you approach the per-node shard limit, and treat the count as a capacity metric alongside disk and CPU.
Defaults and sizing guidance change between Elasticsearch releases. Treat these figures as starting points and confirm them against the official documentation for the version you run.
10The Noisy Neighbor Problem
One tenant’s bad afternoon should never become everyone’s outage.
A noisy neighbor is a tenant whose behavior consumes a disproportionate share of shared resources. It is rarely malicious. It is usually a legitimate customer running a huge report, launching a marketing campaign, or importing a decade of history on a Monday morning. Elasticsearch has no built-in per-tenant quota system in the way some databases do, so you assemble fairness from several layers.
In an apartment block, one family running every tap at once can drop the water pressure for the whole building. Fairness comes from pressure valves on each flat, a meter on each pipe, and a bigger pipe for the building’s largest residents.
Layer 1: limit at the edge
The cheapest and most effective controls live in your own application or API gateway, before requests reach Elasticsearch. Apply per-tenant rate limits, cap the size of result pages, restrict the depth of pagination, and forbid the most expensive query shapes for tenants on lower tiers. Because your gateway knows who the tenant is, it can apply different budgets to different plans.
Layer 2: limit inside Elasticsearch
Search timeouts
Ask searches to stop after a time budget and return partial results, so runaway queries cannot hold threads for minutes.
Bucket and clause limits
Caps on aggregation buckets and query clause counts prevent a single request from exploding in memory.
Circuit breakers
Memory-based breakers reject requests that would push the heap past safe limits, protecting the node from crashing.
Expensive query controls
A cluster setting can disable categories of costly queries entirely, useful in strictly shared environments.
Result window limits
Deep pagination is expensive. Keeping the maximum window modest forces cursor-style approaches instead.
Slow logs
Search and indexing slow logs record queries that exceed thresholds, giving you evidence of who is hurting the cluster.
Layer 3: separate the heavy from the light
When logical controls are not enough, use physical separation inside the same cluster. Allocation filtering and node attributes let you pin an index to specific nodes, so a demanding tenant lives on machines that other tenants do not use. Dedicated coordinating nodes for expensive aggregations, and separate ingest capacity for bulk loading, also keep different kinds of work apart.
Protecting the write path
Search is not the only culprit. A tenant that indexes massive volumes causes segment creation, merging and refresh pressure. Two habits help. First, insist on bulk requests of sensible size rather than a storm of single-document writes. Second, queue tenant writes through a message buffer, so bursts are smoothed and a slow cluster applies back pressure to producers rather than dropping data or collapsing.
Identify
Use slow logs and per-tenant request metrics to find which tenant caused the spike.
Contain
Throttle that tenant at the gateway, without touching anyone else.
Isolate
If the pattern repeats, move the tenant to dedicated nodes or a dedicated index with its own capacity.
Prevent
Convert what you learned into a permanent quota or a documented plan limit.
11Security and Data Isolation
Isolation you cannot prove is isolation you do not have.
The security building blocks
Elasticsearch security is built from a few ideas. Authentication proves who a caller is, through usernames, API keys, tokens or single sign-on. Authorization decides what that identity may do, using roles that grant privileges on indices, aliases, clusters and fields. Encryption protects data in transit between nodes and clients, and can protect it at rest on disk. Audit logging records who did what, which is essential evidence when a customer or regulator asks.
Role-based access control
Roles list which indices or aliases an identity can read or write. In index-per-tenant designs, a role per tenant on a name pattern is the core isolation tool.
Document-level security
A role can carry a query that silently restricts which documents are visible. This lets a shared index be protected by the platform itself. It is a paid-tier feature.
Field-level security
Roles can hide chosen fields from certain users, useful when tenants have different permission levels for sensitive columns.
API keys
Scoped, revocable credentials let each tenant service or integration use only the permissions it needs.
Audit logging
Records access and change events so you can show that isolation held during any incident review.
Kibana Spaces
Spaces separate dashboards, saved searches and other saved objects between teams. They organize the interface, they do not by themselves isolate the underlying data.
Security by model
| Model | Primary enforcement | Typical weakness |
|---|---|---|
| Index per tenant | Role per tenant with index name patterns | Overly broad wildcard patterns that match more than intended |
| Shared index | Filtered alias plus role limited to that alias, or document-level security | Application code that bypasses the alias, or a role granting the shared index directly |
| Cluster per tenant | Separate credentials, networks and accounts | Credential sprawl and inconsistent patching across many clusters |
The trusted-proxy pattern
A common and sturdy design keeps Elasticsearch completely hidden from end users. Only your backend talks to it, using service credentials scoped to a tenant. The backend authenticates the end user, looks up the tenant, and uses that tenant’s alias or credentials. This means a bug in the browser or a stolen end-user token cannot reach the search layer directly. The important discipline is that the tenant identity must come from the authenticated session, never from a value the client can freely send.
Problem
The tenant identifier is taken from a request parameter, and the backend adds it to a filter using the shared index directly.
Why It’s Harmful
Anyone who can change the parameter can read another tenant’s data. A single missed filter in any code path becomes a cross-tenant leak.
Correct Approach
Derive the tenant from the verified identity, search only through tenant-scoped aliases or credentials, and back this with roles so that even buggy code cannot reach other tenants’ data.
Isolation is not only about returned documents. Result counts, aggregation totals, error messages, autocomplete suggestions and relevance scores can all leak information about other tenants if they are computed across shared data. Test for these leaks deliberately.
Testing isolation
Treat cross-tenant access as a class of bug that deserves its own automated tests. Create two test tenants with overlapping content, then verify that every search path, count, suggestion, export and administrative function returns only the caller’s data. Run these tests in your continuous delivery pipeline, and repeat them whenever you upgrade Elasticsearch or change a role.
12Relevance, Analysis and Per-Tenant Customization
Search quality is a tenant-visible feature, and sharing changes it in ways people rarely expect.
How relevance is scored
Elasticsearch ranks documents using a scoring formula called BM25 by default. In simple terms, a word that is rare across the collection is treated as more meaningful than a word that appears everywhere. The statistics that decide how rare a word is are gathered per shard, not across the whole index.
If a word is rare, it is like a rare stamp: finding it says something important. But “rare” depends on which collection you compare to. In a stamp club for one country, a certain stamp is common. In a general fair, it is rare. If tenants share a shard, everyone is judged against the same mixed collection.
What this means for a shared index
In a pooled design, the term statistics on a shard mix content from many tenants. A tenant in the legal industry sharing a shard with a tenant in the cooking industry will have its rare-word signals distorted by the other’s vocabulary. The results remain sensible for most uses, but ranking can shift as other tenants come and go, and small tenants can see surprising behavior. There is also a subtle privacy angle: scores computed from a shared distribution encode a little information about the shared data.
There are three responses. You can accept the small distortion, which is fine for many products. You can use a search type that gathers global statistics first, at the cost of an extra round trip. Or you can separate tenants whose ranking quality matters most into their own indices, where statistics are purely theirs.
Analyzers, synonyms and languages
Analysis is the process of breaking text into searchable pieces, including lowercasing, splitting words, removing endings and applying synonyms. Different tenants often want different behavior: different languages, different synonyms for their own jargon, different handling of product codes. Index-per-tenant handles this gracefully because analyzers are index settings. In a shared index, the analyzer is fixed for a field, so per-tenant variations require workarounds such as separate fields per language or a query-time synonym approach managed centrally.
Language fields
Store text in a field per supported language and choose which field to search based on the tenant’s configured language, rather than one field that tries to serve everyone.
Managed synonym sets
Recent versions of Elasticsearch include a synonyms feature that can be updated without rebuilding an index. Check that your version supports it, and design synonym scope carefully, since one tenant’s synonyms must not change another’s results.
Per-tenant boosting and ranking rules
Many tenants want to promote certain items. Implement this as data, such as boost values in query time logic derived from the tenant’s configuration, rather than as separate schemas.
When sharing is fine for relevance
- All tenants have similar content and vocabulary
- Ranking is a filter-and-sort experience, such as by date or price
- Products can tolerate small shifts in ordering
When to separate for relevance
- Tenants differ sharply in domain, language or vocabulary
- Search quality is the product the tenant pays for
- Contracts demand tenant-specific tuning or analyzers
13Data Lifecycle, Retention and Tenant Offboarding
Every tenant eventually changes plans, shrinks, leaves or asks you to erase their data.
Lifecycle management basics
Elasticsearch includes index lifecycle management, which moves indices through phases as they age. A hot phase handles active writing and searching, a warm phase keeps data searchable on cheaper hardware, a cold phase uses even cheaper storage, and a delete phase removes data at a set age. For time-based data such as logs, events and metrics, data streams combine with rollover so that new backing indices are created automatically when one grows too large or too old.
Think of a store’s stockroom. Fresh, popular items sit near the front where they are grabbed constantly. Older items go to shelves further back, then to a warehouse, and finally to the recycling bin. Lifecycle management is the schedule that moves things along without anyone remembering to do it.
Retention per tenant
Different plans often promise different retention: seven days for a free tier, ninety days for a standard tier, several years for enterprise. The model you chose decides how hard this is.
| Model | How per-tenant retention works | Difficulty |
|---|---|---|
| Index per tenant | Attach a lifecycle policy that matches the tenant’s plan to that tenant’s indices | Easy |
| Shared index | Scheduled delete-by-query jobs per tenant, or separate shared indices grouped by retention class | Hard |
| Cluster per tenant | Configure the policy in that cluster | Easy but repeated |
A neat compromise for pooled designs is to create separate shared index families by retention class, for example a short-retention pool and a long-retention pool. Each family has one lifecycle policy, and moving a tenant between plans becomes a data move rather than a per-document cleanup.
Offboarding and the right to erasure
When a tenant leaves, or when privacy law obliges you to delete someone’s data, you need a clear, verifiable procedure. In an index-per-tenant design, you delete the indices and remove aliases and roles, and the files are gone. In a shared index, you run delete-by-query, which marks documents as deleted and depends on background merging to reclaim space, and you must think about snapshots too, because backups may still contain the deleted data.
Disable access
Revoke roles, API keys and aliases for the tenant so no new reads or writes occur.
Export if required
Provide the tenant a copy of their data in the agreed format before deletion.
Delete the data
Drop dedicated indices, or delete matching documents in shared ones, and record the action for audit.
Address backups
Let snapshots containing the tenant age out under a documented schedule, and state that schedule in your privacy commitments.
Confirm and certify
Verify by searching that nothing remains, and issue a deletion confirmation if the customer’s contract requires one.
Snapshots are taken per index. In a shared-index design, restoring one tenant means restoring the whole index somewhere else and extracting that tenant’s documents. Plan for this in advance, because it is slow and awkward during an emergency.
14Capacity Planning, Rebalancing and Tenant Migration
Tenants never stay the size they started. Your design must let them move.
Sizing with skew in mind
Tenant sizes in a real platform follow a long-tail pattern. A handful of tenants may account for most of your data and traffic, while thousands account for very little. Capacity planning based on the average tenant is therefore misleading. Plan around percentiles: what do the top one percent look like, what does a typical tenant look like, and how quickly are tenants moving between those groups?
Tools for changing shape
Reindex
Copies documents from one index to another, optionally filtered. This is the main tool for moving one tenant out of a pool into a dedicated index.
Split
Increases the number of primary shards of an index by a fixed multiple, when a shared index has outgrown its shard count.
Shrink
Reduces the number of primary shards, useful after a tenant’s data has become read-only and small.
Rollover
Starts a fresh index when the current one is too big or old, keeping shard sizes healthy.
Allocation filtering
Moves an index onto chosen nodes without changing its contents, ideal for relocating a growing tenant to stronger hardware.
Cross-cluster replication and search
Copies or queries data across clusters, supporting regional tenants and gradual moves between clusters.
sequenceDiagram
participant Reg as Tenant registry
participant Pool as Shared index
participant Ded as Dedicated index
participant App as Application
App->>Reg: Read tenant location
Reg-->>App: Pool
Note over Reg,Ded: Tenant crosses size threshold
Reg->>Ded: Create dedicated index from template
Pool->>Ded: Reindex tenant documents
App->>Ded: Dual write during catch-up
Reg->>Reg: Switch location to Dedicated
App->>Ded: Reads and writes now go here
Pool->>Pool: Delete tenant documents after safety period
The golden rules of migration
First, never move a tenant without a way back. Keep the source data intact until the new location has been verified. Second, handle writes that arrive during the copy, either by writing to both places temporarily or by replaying a change log. Third, switch traffic through the registry so the change is atomic from the application’s point of view. Fourth, verify counts and sample documents rather than trusting that the copy job reported success.
Rehearse migration on a low-risk tenant regularly. A migration procedure that has never been run is a hope, not a capability.
15Monitoring, Metering and Governance
You cannot be fair to tenants you cannot measure.
Two kinds of monitoring
Platform monitoring watches the health of the cluster: heap use, garbage collection, CPU, disk, thread pool queues, shard counts, cluster state size and recovery activity. Tenant monitoring watches how each customer uses the platform: request rate, latency, error rate, indexing volume, storage and expensive query counts. Most teams do the first well and the second poorly, which is why noisy neighbors take so long to find.
Storage per tenant
Easy in index-per-tenant designs through index statistics. In shared indices you must estimate from document counts or maintain your own counters.
Query cost per tenant
Record latency and shards touched for each search at the gateway, tagged with the tenant identifier.
Indexing rate per tenant
Measure documents and bytes written, again at the gateway or ingestion pipeline, since Elasticsearch does not attribute it to tenants for you.
Error and rejection rates
Rejected requests and timeouts by tenant reveal who is hitting limits and who is being harmed by others.
Shard and mapping growth
Track the counts that consume your hidden budgets, before they become emergencies.
Tagging everything at the edge
The most reliable technique is to make your API gateway or search service the measurement point. Every request passes through it with a verified tenant identity, so it can attach the tenant to logs, metrics and traces. Elasticsearch can also record an opaque identifier header on requests, which appears in slow logs and task listings, making it possible to trace a slow operation back to a tenant.
Metering and billing
If you charge by usage, measure with the same care as a utility company. Use documents stored, bytes stored, queries served and indexing volume, and keep those counters in a durable place that is not the same cluster being measured. In pooled designs, storage attribution is approximate unless you maintain counters, so design your billing promises around what you can honestly measure.
Governance: who is allowed to change what
Automate tenant lifecycle
Create, upgrade, migrate and delete tenants through code with review, not by hand in a console.
Version templates and policies
Keep index templates, roles and lifecycle policies under version control, and roll them out gradually.
Separate platform and tenant permissions
Very few people should be able to touch cluster-wide settings or read across tenants, and their actions should be audited.
Alert on shared-budget consumption
Watch shard count, field count and cluster state size just as you watch disk space.
16Design Patterns and Anti-Patterns
A short catalogue of what works, and what quietly hurts.
Patterns worth adopting
Tenant registry as the single source of truth
All location, routing and quota information lives in one place, so the rest of the platform never guesses where a tenant is.
Tiered isolation
Match isolation strength to what each tenant pays and requires. Start small tenants in the pool and graduate them.
Alias-per-tenant as the only entry point
Applications never see the physical index names. Aliases carry filters, routing and access rules, and let you swap the underlying storage without code changes.
Defense in depth
Combine application checks, tenant-scoped aliases, roles and, where available, document-level security so no single mistake exposes data.
Budget-first design
Decide limits for shards, fields, query cost and payload size before launch, and enforce them at the edge.
Anti-patterns to avoid
Problem
Using default shard settings for every tenant index, including tenants with a few hundred documents.
Why It’s Harmful
Shard counts explode, memory is wasted on empty capacity, and recovery after restarts becomes painfully slow.
Correct Approach
Give small tenants a single primary shard, or pool them, and reserve larger shard counts for tenants whose data actually needs them.
Problem
Letting every tenant query with unlimited freedom: deep pagination, huge aggregations, wildcard searches with leading wildcards.
Why It’s Harmful
One tenant’s expensive query can exhaust memory or threads and slow every other tenant, with no simple way to stop it after the fact.
Correct Approach
Expose a curated search interface, cap result windows and bucket counts, apply timeouts, and rate limit by tenant and plan.
Problem
Wildcard role patterns such as granting a tenant access to any index whose name begins with a common prefix.
Why It’s Harmful
A tenant named similarly to another, or a new internal index that shares the prefix, can be exposed unintentionally.
Correct Approach
Use precise, generated names and aliases, validate tenant identifiers strictly, and test roles for over-matching.
Problem
Choosing one isolation model forever, with no path to move a tenant to another tier.
Why It’s Harmful
Tenants that outgrow the model become problems, and the migration you never planned becomes a crisis migration.
Correct Approach
Build the registry and the migration tooling early, even if you only use them rarely at first.
Best practices at a glance
Do
- Decide a maximum tenant count and a plan for approaching it
- Keep mappings strict and use flattened fields for tenant-defined data
- Route and filter through aliases, and secure them with roles
- Meter per tenant at the gateway
- Test isolation automatically
Do Not
- Trust a client-supplied tenant value
- Create one shard-heavy index per tiny tenant
- Allow unbounded dynamic fields
- Assume filters alone equal security
- Wait for an incident to build quotas
17Real-World Scenarios
Four common situations, and how the ideas in this guide apply to each.
Customer support software with search across tickets
Thousands of small businesses each have a modest number of tickets. This is the classic long tail, so a pooled shared index with tenant-based routing and filtered aliases keeps costs low. The few very large customers are graduated to dedicated indices. Sensitive attachments and internal notes use field-level restrictions where the plan allows.
E-commerce marketplace with many sellers
Sellers rarely need isolated searching, because shoppers search across all of them. Here the seller is a filter on shared product data, not a hard tenant boundary. The isolation concern is instead protecting seller-specific dashboards and analytics, which use filtered aliases.
Managed logging or security analytics platform
Each customer sends large, continuous streams of events. Data streams with rollover, one set per tenant or per tenant group, fit well. Retention differs by plan, so lifecycle policies attach per tenant. Large customers get dedicated nodes, and regulated customers get regional clusters queried through cross-cluster search.
Enterprise internal platform with many teams
Teams are tenants, but they share a corporate identity system. Index-per-team with role mapping from the company directory works well, and Kibana Spaces give each team its own dashboards. Cost allocation by team relies on per-index storage statistics and gateway-level query metrics.
Large multi-site search deployments are often described as using one index per site or language edition, which is the index-per-tenant idea applied to content collections. Publicly documented examples exist for wiki-style platforms, and the engineering write-ups from those teams are worth reading for their sizing and operational lessons.
A decision walk-through
Do contracts forbid shared infrastructure?
If yes, use dedicated clusters or deployments for those tenants, and stop here for them.
Will you have more than a few thousand tenants?
If yes, pool the long tail in shared indices with routing and aliases, and keep dedicated indices for the largest.
Do tenants need custom schemas or analyzers?
If yes, favor index per tenant, or use flattened fields and per-language fields if pooling.
Is per-tenant deletion, export or restore frequent?
If yes, dedicated indices make life dramatically easier.
Whatever you pick, build the registry and migration tools
Your first answer will not be your last, so make the change cheap.
18Frequently Asked Questions
No. The best model depends on tenant count, size skew, compliance needs and team capacity. Most mature platforms end up with a tiered mixture rather than one pure model.
It depends on hardware, version and mappings. What is certain is that every index and shard consumes memory and cluster coordination effort, so count them, set alerts, and treat the per-node shard limit as a warning sign rather than a target.
Not on its own. A filter depends on every code path remembering to add it. Use tenant-scoped aliases, roles, and where available document-level security, so the platform enforces the boundary.
No. Routing is a performance optimization that sends a tenant’s data to fewer shards. It does not stop a query without the right filter from reading other tenants’ documents.
In a shared index it can create hot shards. Options include a routing partition size to spread the tenant, or moving it to a dedicated index or dedicated nodes, ideally through a planned migration process.
Easily with index per tenant, because analyzers are index settings. In a shared index you need workarounds such as per-language fields or centrally managed synonym sets.
Deletions mark documents as removed, and physical cleanup happens later during segment merging. Dedicated indices avoid this, because dropping the whole index removes its files directly.
Spaces separate saved objects like dashboards and visualizations for different teams. Data access still has to be controlled by roles on indices and aliases.
Layer your defenses: rate limits at the gateway, timeouts and limits inside Elasticsearch, per-tenant monitoring, and physical separation of heavy tenants onto dedicated nodes or clusters.
Yes, if you plan for it. A tenant registry, alias-based access and rehearsed reindexing procedures let you move tenants between models with little disruption.
The core concepts, shards, routing, aliases and cluster state costs, are shared by the two projects, but security features, defaults and terminology differ, so verify each capability in the documentation of the product and version you use.
For thousands of small tenants, usually yes. For a modest number of large or regulated tenants, it is often the right and even the cheapest choice once you count the risk and the engineering effort of complex isolation.
19Summary and Key Takeaways
Multi-tenancy in Elasticsearch is the craft of letting many customers share one search platform while each feels alone in it. There is no free lunch. Index-per-tenant gives clean isolation and flexible settings but spends your shard and metadata budget quickly. Shared indices with routing and filtered aliases scale to enormous tenant counts but demand careful security, schema discipline and fairness controls. Dedicated clusters give the strongest boundaries at the highest operational cost. The wisest platforms mix these, use a registry to know where every tenant lives, enforce isolation with roles rather than good intentions, measure usage per tenant, and rehearse moving tenants as they grow. Build the walls, the meters and the moving trucks before you need them.
Key Takeaways
- Think in budgets — shards, fields and shared compute are finite, and every tenancy model spends them differently.
- Choose on the spectrum — silo, bridge and pool trade isolation against cost, and most real systems use tiers.
- Enforce isolation in the platform — use tenant-scoped aliases, roles and, where available, document-level security instead of relying on application filters.
- Control the schema — strict mappings and flattened fields prevent mapping explosion in shared indices.
- Engineer for fairness — combine gateway rate limits, query guardrails, per-tenant metrics and physical separation for heavy tenants.
- Plan the lifecycle — retention, offboarding, backups and erasure are far easier with dedicated indices, so design pooled tiers with these tasks in mind.
- Make tenants movable — a tenant registry and rehearsed migration tooling turn growth from a crisis into a routine operation.