A cross-index query in Elasticsearch is any search that targets more than one index in a single request. The query body is identical to a single-index search; the multi-target part is purely in the path - a comma-separated list, a wildcard, an alias, or a data stream. Elasticsearch fans the request out to every matching shard, runs the query locally, and merges the per-shard hits on the coordinating node. The pattern is the standard way to search time-series data, sharded tenants, and partitioned domain indices without rewriting queries per index.
When to Use Cross-Index Queries
| Pattern | Example target | Notes |
|---|---|---|
| Comma-separated list | index1,index2,index3 |
Explicit and stable across cluster changes. |
| Wildcard | logs-2026-* |
Resolves at request time; convenient for time-series. |
| Alias | current-logs |
Decouple query from index naming; supports filtered aliases. |
| Data stream | logs-app-default |
Modern replacement for date-named indices + alias. |
| Cross-cluster search | remote:logs-* |
Federate across Elasticsearch clusters. |
How Cross-Index Queries Execute
The coordinating node resolves the target expression to a concrete list of indices and then to a list of shards. With pre_filter_shard_size (default 128 since 7.6) and can_match enabled, the coordinator first asks each shard whether it can possibly match the query (cheap range checks against the shard's segment-level min/max for the queried field) and skips shards that cannot. This is the primary optimization that makes cross-index queries against thousands of time-series indices affordable - shards outside the time range short-circuit before the real query runs.
GET logs-app-*,metrics-app-*/_search
{
"query": {
"bool": {
"filter": [
{ "range": { "@timestamp": { "gte": "now-1h" } } },
{ "term": { "host.name": "web-01" } }
]
}
}
}
The can_match phase trims shards outside the last hour without reading them. The matching shards run the query in parallel; the coordinator merges, sorts, and trims to size.
Cross-Index Mapping Compatibility
Indices in a cross-index query do not have to be identical, but fields that the query references must be compatible. Specifically:
- A field referenced by query, sort, aggregation, or script must have the same type in every targeted index. A field that is
longin one andkeywordin another fails the search withCannot use [field] of type [long] and [keyword] on the same query. - Multi-field structure may differ; only the leaf actually used must match.
- Indices that don't define the field at all are skipped silently for that clause.
- Use the Field Capabilities API (
GET /<targets>/_field_caps?fields=*) to audit compatibility across the target set before a cross-index query goes to production.
This is also the root cause of IllegalArgumentException: mapper conflicts when wildcards bring incompatible indices into the same query.
Common Pitfalls With Cross-Index Queries
- Wildcards that quietly grow over time.
logs-*started with five indices and now matches five thousand. Use date-bounded patterns (logs-2026-05-*) or aliases to bound fan-out. - Sort or aggregate on a field that differs in type across indices. Even one mismatched index causes the whole request to fail.
- Disabling
can_match(pre_filter_shard_size: 0orindex.search.idle.aftertuning) and paying the full fan-out cost on every query. - Ignoring
ignore_unavailable. If even one wildcard target is missing or closed, the query fails unless you passignore_unavailable: trueandallow_no_indices: true. - Using cross-index queries when an alias with a filter or a data stream would express the intent better and survive index rollovers.
Operating Cross-Index Queries at Scale
The cost of a cross-index query is approximately linear in the number of shards visited after can_match filtering. Two operational levers matter most: shard size (keep individual shards in the 10-50 GB range so per-shard query latency stays predictable) and the targeted index pattern (narrow it so wildcards don't drag in cold indices). Pulse profiles cross-index queries and surfaces the ones that fan out to far more shards than they need to, traces the culprit wildcard or alias, and recommends the index pattern or alias change that reduces fan-out without changing query semantics.
Frequently Asked Questions
Q: How do I query multiple indices in Elasticsearch in one request?
A: Put a comma-separated list or wildcard in the path: GET /index1,index2/_search, GET /logs-2026-*/_search, or target an alias or data stream. The query body is identical to a single-index search; Elasticsearch fans out to every matching shard and merges results on the coordinating node.
Q: What happens if mappings differ across indices in a cross-index query?
A: For any field referenced by the query (in query, sort, aggregations, or scripts), the type must match in every targeted index. Mismatches throw a search-time exception. Use the Field Capabilities API to verify compatibility, and consider an alias with a filter when only a subset of indices is mapping-compatible.
Q: Is there a limit on how many indices I can query at once?
A: There is no hard ceiling on the number of indices, but the practical limit is shards, not indices. Coordinating-node memory and the action.search.shard_count.limit cluster setting (default 1000) cap how many shards one search can touch. Reduce shard count per index (avoid over-sharding small indices) before raising the cluster limit.
Q: How does Elasticsearch handle field mapping conflicts across indices?
A: At query time, it fails fast on referenced fields with mismatched types. Unreferenced mismatched fields don't affect the query. The Field Capabilities API reports which indices conflict for which field. The durable fix is to reindex one side or maintain type consistency via index templates.
Q: Can I use wildcards in cross-index queries?
A: Yes. * matches one or more characters; ? matches a single character. The expression resolves at request time. Use the ignore_unavailable and allow_no_indices parameters to control behavior when no indices match.
Q: How do cross-index queries interact with custom routing?
A: Custom routing optimizes for queries targeting the same routing value within an index. Across indices with different routing schemes, the optimization is lost - Elasticsearch may need to query all shards. If you rely on routing for performance, design the routing key to be stable across the index pattern you query.
Related Reading
- Elasticsearch IllegalArgumentException: mapper conflicts: the field-type mismatch that breaks cross-index queries.
- Elasticsearch join two indexes: when cross-index search isn't enough and you need a join.
- Elasticsearch using date math: bound time-based cross-index queries with date math.
- Elasticsearch create alias with filter: a cleaner abstraction than wildcards.
- Elasticsearch index.mapping.total_fields.limit: related limit when target indices grow many fields.
- Elasticsearch create index with mapping: keep target indices mapping-compatible.