How to manage index aliases in Elasticsearch

Index aliases in Elasticsearch keep client traffic pinned to one fixed name while the backing index changes underneath it. That makes rollovers, reindex cutovers, and staged validation possible without retargeting every shipper, dashboard, or application that writes to the cluster.

Aliases live in cluster state and are changed through the /_aliases API, which can add, remove, and swap bindings in a single atomic request. An alias can point to one or many indices, and setting is_write_index ensures indexing requests continue to land on the intended destination after a cutover.

Examples here use plain indices named logs-2025.03 and logs-2025.04 to avoid the built-in data stream patterns that current Elastic stacks reserve for names such as logs-*-*. Security-enabled clusters need the correct HTTPS endpoint plus authentication, and alias changes are safest only after the destination index has been populated, checked, and the cluster reports the expected health state.

Steps to manage Elasticsearch index aliases:

  1. Check the current alias target before making changes.
    $ curl -sS --fail "http://localhost:9200/_cat/aliases/logs-*?v&h=alias,index,is_write_index"
    alias        index        is_write_index
    logs-current logs-2025.03 true

    The _cat APIs are intended for human-readable terminal checks. Use the JSON-based /_alias endpoints in scripts or automation.

  2. Add a temporary validation alias to the destination index.
    $ curl -sS --fail -H "Content-Type: application/json" -X POST "http://localhost:9200/_aliases?pretty" -d '{
      "actions": [
        { "add": { "index": "logs-2025.04", "alias": "logs-next" } }
      ]
    }'
    {
      "acknowledged" : true,
      "errors" : false
    }

    A separate validation alias keeps production traffic on logs-current while queries or dashboards are checked against logs-next.

  3. Move the logs-current write alias to the new index in one request.
    $ curl -sS --fail -H "Content-Type: application/json" -X POST "http://localhost:9200/_aliases?pretty" -d '{
      "actions": [
        { "remove": { "index": "logs-2025.03", "alias": "logs-current", "must_exist": true } },
        { "add": { "index": "logs-2025.04", "alias": "logs-current", "is_write_index": true } }
      ]
    }'
    {
      "acknowledged" : true,
      "errors" : false
    }

    Setting must_exist on the remove action makes the request fail if the expected old alias binding is missing, which protects the cutover from stale assumptions about the current target.

    Switch writes only after the destination index has the required mappings and document set.

  4. Inspect the alias definition after the cutover.
    $ curl -sS --fail "http://localhost:9200/_alias/logs-current?pretty&filter_path=*.aliases.*.is_write_index"
    {
      "logs-2025.04" : {
        "aliases" : {
          "logs-current" : {
            "is_write_index" : true
          }
        }
      }
    }

    On secured clusters, replace http://localhost:9200 with the cluster HTTPS endpoint and add authentication such as -u elastic:password or an API key header.

  5. Write a validation document through the alias and confirm the request lands on the new index.
    $ curl -sS --fail -H "Content-Type: application/json" -X PUT "http://localhost:9200/logs-current/_doc/alias-proof?refresh=wait_for&pretty" -d '{
      "message": "alias write test",
      "level": "info"
    }'
    {
      "_index" : "logs-2025.04",
      "_id" : "alias-proof",
      "_version" : 1,
      "result" : "created",
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "failed" : 0
      },
      "_seq_no" : 1,
      "_primary_term" : 1
    }

    The returned _index value is the decisive proof that the write alias now points to the intended destination.

  6. Read the validation document from the destination index.
    $ curl -sS --fail "http://localhost:9200/logs-2025.04/_doc/alias-proof?pretty&_source=message,level"
    {
      "_index" : "logs-2025.04",
      "_id" : "alias-proof",
      "_version" : 1,
      "_seq_no" : 1,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "message" : "alias write test",
        "level" : "info"
      }
    }
  7. Remove the temporary alias after validation is complete.
    $ curl -sS --fail -H "Content-Type: application/json" -X POST "http://localhost:9200/_aliases?pretty" -d '{
      "actions": [
        { "remove": { "index": "logs-2025.04", "alias": "logs-next", "must_exist": true } }
      ]
    }'
    {
      "acknowledged" : true,
      "errors" : false
    }

    Keep the validation alias only when a staged consumer still needs it; otherwise remove it so application paths stay unambiguous.