Running searches across multiple Elasticsearch clusters makes it possible to query production, archive, or disaster-recovery data with one request, keeping dashboards and investigations consistent without copying indices between clusters.

In cross-cluster search, the local cluster receives a standard Search API request over HTTP, forwards it to configured remote clusters over the transport connection, and merges the results into a single response. Remote indices are addressed by prefixing the index pattern with the remote cluster alias in the form <alias>:<index-pattern>.

A remote cluster connection must exist before the alias can be used, and security-enabled clusters require authenticated requests with privileges that cover the targeted indices. Cross-cluster searches can add latency or load when many shards are queried, so the _clusters section should be checked for skipped, partial, or failed cluster execution.

  1. Configure the remote cluster connection using a cluster alias.

    Remote indices are referenced as dr-site:logs-* where dr-site is the configured alias.

  2. Confirm the remote cluster is connected using the remote info API.
    $ curl --silent --show-error "http://localhost:9200/_remote/info?pretty&filter_path=*.connected,*.mode,*.num_nodes_connected"
    {
      "dr-site" : {
        "connected" : true,
        "mode" : "sniff",
        "num_nodes_connected" : 2
      }
    }

    connected must be true for the alias to be usable in cross-cluster search.

  3. Run a cross-cluster search query against a remote index pattern.
    $ curl --silent --show-error -H "Content-Type: application/json" -X GET "http://localhost:9200/dr-site:logs-*/_search?pretty&filter_path=_clusters.total,_clusters.successful,_clusters.skipped,_clusters.running,_clusters.partial,_clusters.failed,hits.total,hits.hits._index,hits.hits._id" -d '{
      "size": 1,
      "track_total_hits": true,
      "query": {
        "match_all": {}
      }
    }'
    {
      "_clusters" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "running" : 0,
        "partial" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 5,
          "relation" : "eq"
        },
        "hits" : [
          {
            "_index" : "dr-site:logs-2026.01.08",
            "_id" : "doc-1"
          }
        ]
      }
    }

    Broad queries (for example match_all) can increase load on every searched cluster, especially when many shards match.

  4. Run the same search across local plus remote indices by listing multiple index patterns.
    $ curl --silent --show-error -H "Content-Type: application/json" -X GET "http://localhost:9200/logs-*,dr-site:logs-*/_search?pretty&filter_path=_clusters.total,_clusters.successful,_clusters.skipped,_clusters.running,_clusters.partial,_clusters.failed,hits.total" -d '{
      "size": 0,
      "track_total_hits": true,
      "query": {
        "match_all": {}
      }
    }'
    {
      "_clusters" : {
        "total" : 2,
        "successful" : 2,
        "skipped" : 0,
        "running" : 0,
        "partial" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 13,
          "relation" : "eq"
        }
      }
    }
  5. Verify each cluster reports a successful status in the _clusters.details section.
    $ curl --silent --show-error -H "Content-Type: application/json" -X GET "http://localhost:9200/logs-*,dr-site:logs-*/_search?pretty&filter_path=_clusters.total,_clusters.successful,_clusters.details.*.status" -d '{
      "size": 0,
      "query": {
        "match_all": {}
      }
    }'
    {
      "_clusters" : {
        "total" : 2,
        "successful" : 2,
        "details" : {
          "(local)" : {
            "status" : "successful"
          },
          "dr-site" : {
            "status" : "successful"
          }
        }
      }
    }

    Any skipped, partial, or failed status indicates incomplete results for at least one cluster.