LearnThatStack Ace your next interview

Elasticsearch

Kibana Dev Tools requests for Elasticsearch 8 and 9 Checked Oct 2026 92 commands

The model

  • Elasticsearch splits an index into primary shards, each a Lucene index. hash(_routing) % primaries picks a document's shard, so the primary count can't change once the index exists.
  • A replica is a copy of a primary on another node. It takes over when the primary fails, and it serves searches too.
  • Search is near real time. A write goes to a memory buffer and the translog. A refresh, every second by default, makes it searchable.
  • An analyzer splits a text field into terms. The inverted index maps each term to the documents that hold it. A keyword field keeps the whole value as one term.
  • In filter context, a clause only decides whether a document matches, and Elasticsearch can cache the result. In query context, it also adds to the BM25 relevance score.
Clientapp or KibanaCoordinating nodeany nodePrimary shardpicked by hashReplicason other nodesWRITEPUT _doc/1route hash(_id) % nreplicatedone replicas have it201 not searchable yetSEARCHGET _searchquery every shardtop IDs and scoresfetch top hits
A write goes to one primary, picked by a hash of _id, then to its replicas. A search asks one copy of every shard for its top hits, then fetches them.

Cluster, shards & nodes

how one index spreads across machines

What Elasticsearch is

Say what Elasticsearch isA distributed search and analytics engine on Lucene. Teams use it for full-text search, logs and metrics.
Say how it differs from a relational databaseIt scales out by adding nodes and stores denormalized JSON. It has no joins or ACID transactions.
Name the parts of the ELK StackLogstash parses data, Elasticsearch stores and searches it, and Kibana shows it.

TrapAn index is closer to a table than to a database. 8.0 removed mapping types, so each index has one mapping.

Shards and replicas

Create an index with 3 primaries, 1 replica each"number_of_shards": 3"number_of_replicas": 1
Change the replica countPUT /logs/_settingsYou can change it any time. The primary count is fixed.
Say how a document picks its shardhash(_routing) % primaries, where _routing defaults to the _id.
Give an index more primariesPOST /logs/_split/logs-splitIt builds a new index, because the primary count can't change.
Add a data nodeelasticsearch -E cluster.name=prodElasticsearch moves shards onto it.

TipAim for 10GB to 50GB a shard. Plan enough shards so new nodes have some to take over.

TrapA replica never shares a node with its primary. On a one-node cluster, replicas stay unassigned and health is yellow.

Node roles and failover

Run a dedicated master nodenode.roles: [ master ]The elected master creates indices and allocates shards.
Store shards and run searchesnode.roles: [ data ]
Transform documents before indexingnode.roles: [ ingest ]
Only route requests and merge resultsnode.roles: [ ]Every node coordinates too.
Say what happens when a node failsA replica takes over each lost primary. Then Elasticsearch builds new replicas on the healthy nodes.
Say how Elasticsearch prevents split brain (7.0+)A master needs votes from a majority, so only one side of a network split can elect one.
Pick how many master-eligible nodesThree. An election needs a majority, so three survive losing one.

TipWith no node.roles, a node takes every default role. Use dedicated roles in production.

TrapBefore 7.0, a wrong discovery.zen.minimum_master_nodes allowed split brain. 8.0 removed the setting.

OpenSearch and Solr

Say what OpenSearch isA fork of Elasticsearch 7.10.2 that AWS made in 2021, under the Apache 2.0 license.
Say how Solr differsIt's also built on Lucene, but SolrCloud needs ZooKeeper. Solr is Apache 2.0 and uses XML configuration.

TrapElasticsearch hasn't been Apache 2.0 since 2021. It's Elastic License 2.0 or SSPL, plus AGPLv3 since 2024.

Documents & writes

write, read and version one document

CRUD and bulk

Create a document, or replace itPUT /users/_doc/1It overwrites the whole document if ID 1 exists.
Write only if the ID is newPUT /users/_create/1It fails with 409 Conflict if the ID exists.
Read a documentGET /users/_doc/1
Change some fieldsPOST /users/_update/1Send the changed fields in doc.
Delete a documentDELETE /users/_doc/1
Send many writes in one requestPOST /_bulkPut an action line before each document. Aim for 1 to 15MB a request.
Delete every document that matches a queryPOST /logs/_delete_by_query

TrapAn update still rewrites the whole document. Segments never change, so Elasticsearch only marks the old version deleted.

Versions and conflicts

Write only if nobody changed it since you read it?if_seq_no=2&if_primary_term=1Send back the _seq_no and _primary_term you read.
Use the version from your source database?version=100&version_type=externalElasticsearch writes only if your version is higher.

TipOn a 409 conflict, read the document again and retry.

TrapSince 7.0 you can't check for conflicts with the internal _version. It only counts changes.

Refresh and the translog

Say when a new document becomes searchableAfter the next refresh, every second by default.
Make one write searchable at once?refresh=trueIt forces a refresh, which is expensive.
Wait until the write is searchable?refresh=wait_for
Refresh an index less often"refresh_interval": "30s"-1 turns it off for a bulk load.
Say why an acknowledged write survives a crashThe translog, a write-ahead log synced on every request. Elasticsearch replays it on restart.

TipA refresh writes a new Lucene segment. A flush commits segments to disk and starts a new translog.

Analysis & mappings

how each field is analyzed and stored

Analyzers and the inverted index

Say what an inverted index isA map from each term to the documents that hold it, like the index of a book.
Say why it's fastA search looks up its terms and merges their document lists. It never scans documents.
Name an analyzer's steps, in orderCharacter filters clean the text, a tokenizer splits it, and token filters change the tokens.
Name the built-in analyzersstandard, the default, plus simple, whitespace, keyword and english.
Build a custom analyzer"tokenizer": "standard""filter": ["lowercase", "stop"]Define it under analysis in the index settings.

TrapToken filters run in order. Put lowercase before stop, or stop misses The.

Text or keyword field

"type": "text"Search a field word by word
"type": "keyword"Match, sort or aggregate the whole value
"fields": {"keyword": {"type": "keyword"}}Search name, and sort on name.keyword.Get both from one field
worksdoesn't work

TipDynamic mapping sets ignore_above: 256 on .keyword, so longer strings can't be matched exactly.

Mappings and dynamic mapping

Show an index's mappingGET /products/_mapping
Name the main field typestext, keyword, long, double, date, boolean, object, nested, geo_point and ip.
Say what type a new field getsA string becomes text plus .keyword, or date if it looks like one. A whole number becomes long.
Reject documents with unknown fields"dynamic": "strict"false keeps them in _source but doesn't index them.
Map every new string as keyword"match_mapping_type": "string"Put it in a dynamic template.

TipA field for every new key is a mapping explosion. An index allows 1,000 fields by default.

TrapYou can add fields, but you can't change an existing field's type. That needs a new index and a reindex.

Doc values and fielddata

Say what sorting and aggregations readDoc values, an on-disk copy of each field's values, stored by column. text fields have none.
Aggregate on a text field anyway"fielddata": trueIt loads the field into the JVM heap. Use a keyword sub-field instead.

TipSet "doc_values": false on a field you never sort or aggregate on. It saves disk.

Relationships without joins

Model related data, by defaultDenormalize. Copy the author's name into every post.
Keep each object in an array separate"type": "nested"Each object becomes a hidden document. Search it with a nested query.
Change children without reindexing the parent"type": "join"Parent and child share a shard. has_child queries are slow.

TrapElasticsearch flattens an object array. Alice rated 5 and Bob rated 1, so a search for alice with a 1 still matches.

Aggregations

group and measure the matching documents

Bucket, metric and pipeline aggregations

Group documents into buckets"terms": {"field": "brand"}range and date_histogram also make buckets.
Compute a value for each bucket"avg": {"field": "price"}sum, min and max work the same way.
Compute from other aggregations' results"cumulative_sum": {"buckets_path": "sales"}A pipeline aggregation, here a running total.
Break each bucket down againNest an aggs block inside the bucket aggregation.

TrapThe nested aggregation isn't a sub-aggregation. It aggregates the inner documents of a nested field.

Date histograms

Bucket sales by calendar month"calendar_interval": "month"Each bucket has as many days as its month.
Bucket by a fixed span, like 12 hours"fixed_interval": "12h"
Drop empty buckets"min_doc_count": 1extended_bounds adds empty buckets past the data.

Trapcalendar_interval takes one unit, like 1d. A multiple like 2d needs fixed_interval.

Index management

aliases, reindexing, templates, lifecycle and backups

Aliases and reindexing

Swap the index behind an alias at oncePOST /_aliasesSend a remove and an add together. Searches never see a gap.
Show only error logs through an alias"filter": {"term": {"level": "error"}}A filtered alias.
Create a new index with the fixed mappingPUT /products_v2Reindex copies no settings or mappings.
Copy the documents acrossPOST /_reindex?wait_for_completion=falseIt runs as a task. Then swap the alias.
Delete the old indexDELETE /products_v1
Rename a field without reindexing"type": "alias"A field alias.

TipAliases also give many monthly indices one name, and keep old names working for old clients.

TrapWrites during the copy need a plan. A second pass with op_type: create adds missed documents, but not updates or deletes.

Index templates

Give every new logs-* index the same settingsPUT /_index_template/logsSet index_patterns, then put settings, mappings and aliases under template.
Reuse blocks across templatesPUT /_component_template/baseList them in composed_of.
Decide which template wins"priority": 600The higher one wins. Built-in ones use 100.

TrapPUT /_template makes a legacy template, deprecated since 7.8. Use _index_template.

Lifecycle and data tiers

Name the ILM phasesHot, warm, cold, frozen and delete. An index enters each at its min_age.
Start a new index at 50GB a shard or 30 days"max_primary_shard_size": "50GB""max_age": "30d"The rollover action, in the hot phase.
Delete indices a year after rollover"min_age": "365d"Set it on the delete phase.
Put a node in the hot tiernode.roles: [ data_hot ]Or data_warm, data_cold, data_frozen. ILM moves older indices down the tiers.

TipCold and frozen tiers can use searchable snapshots, which need no replicas. Frozen reads them straight from the repository.

Snapshots and restore

Register where snapshots goPUT /_snapshot/my_backupA shared filesystem, S3, Azure Blob Storage or Google Cloud Storage.
Take a snapshotPUT /_snapshot/my_backup/snap-1Each one is incremental, so frequent snapshots stay cheap.
Restore under new namesPOST /_snapshot/my_backup/snap-1/_restoreSet rename_pattern if the names clash with live indices.
Take snapshots on a schedulePUT /_slm/policy/nightlySnapshot lifecycle management (SLM).

TrapCopying the data folders is not a backup. Snapshots are the only supported way.

Monitor, secure & tune

keep a production cluster healthy and fast

Monitor a cluster

Check cluster healthGET /_cluster/healthYellow means a replica is unassigned. Red means a primary is.
List indices or nodes as a tableGET /_cat/indices?vGET /_cat/nodes?v
Find out why a shard is unassignedGET /_cluster/allocation/explain
Check heap, GC and thread poolsGET /_nodes/stats

TipAlert on heap above 85%, disk above 85%, slow searches and failed indexing.

TrapAt 85% disk, Elasticsearch puts no new shards on a node. At 95%, it blocks writes to that node's indices.

Secure a cluster

Turn security onIt's on by default since 8.0. Before that, set xpack.security.enabled: true.
Encrypt node and client trafficxpack.security.transport.ssl.enabled: truexpack.security.http.ssl.enabled: true
Give an app its own credentialsPOST /_security/api_key
Create a role that reads logs-*POST /_security/role/logs_readerA role can also hide fields and filter documents.

TipTurn on audit logging. Encrypt the disks too, since Elasticsearch doesn't encrypt data at rest.

TrapNever expose port 9200 to the internet. Keep the cluster on a private network behind a firewall.

Tune indexing and search

Load a large data set fast"number_of_replicas": 0Turn refresh off too. Until you add replicas back, a node failure can lose data.
Speed up writes, at a risk"translog.durability": "async"A crash can lose acknowledged writes.
Search one shard instead of all?routing=user42Index the documents with the same value.
Keep the heap out of swapbootstrap.memory_lock: trueLeave the heap size to Elasticsearch, or keep it under 32GB.

TipIndex and search tuning often conflict. Replicas raise search throughput but slow every write.

Found this useful? Pass it on.
Pro · $10/mo

This sheet stays free. With Pro, you can:

  • Every answer on this sheet. Read the full answer to all 49 questions it links, not just the 5 free ones.
  • My sheet. The cards you star and the ones you miss in Quiz me, from every sheet, on one page to quiz and print.
  • PDFs. Download this sheet and My sheet, laid out for A4, with every question a link to its answer.
  • The rest of Pro. Every answer in the question library, and 1,000 AI credits a month.