1. Executive mental model
Elasticsearch is a distributed search and analytics engine written primarily in Java. Each cluster is a set of JVM processes called nodes. Nodes share a single logical view of data through a replicated, master-coordinated cluster state. User-facing work arrives over HTTP (REST) or the internal binary transport protocol; both ultimately dispatch to named actions (TransportAction subclasses) that read or mutate shards — Lucene indexes with an Elasticsearch-specific translog, mapping layer, and replication machinery.
How to reason about changes:
- Metadata mutations (create index, mapping, settings) are master-only cluster-state tasks batched by
MasterService, published to all nodes, applied byClusterApplierService. - Document writes route to a primary shard by routing key, execute on the shard engine, replicate to in-sync replicas, then respond.
- Searches fan out from a coordinating node to shard copies, execute Lucene queries locally, merge results.
- Plugins/modules extend registries (actions, mappers, aggregations, repositories, network) wired during
NodeConstructionvia Guice.
Coordinator, not vanilla Raft) ·
Google Guice (dependency injection in the node)
2. Repository map
What kind of project
A Gradle multi-project Java monorepo shipping a server distribution (tar/zip/deb/rpm/docker), optional plugins, REST API specs, client libraries, and extensive QA. Version 9.5.0 per build-tools-internal/version.properties. Licensed under Elastic License 2.0 / SSPL / AGPL depending on component.
Languages, runtimes, build tools
| Technology | Role | Evidence |
|---|---|---|
| Java 21+ | Build toolchain (CONTRIBUTING.md) | JDK required to compile |
| Bundled JDK 26 | Runtime shipped in distribution | version.properties bundled_jdk |
| Gradle 9.5 | Build orchestration | gradle/wrapper/gradle-wrapper.properties |
| Apache Lucene 10.4 | Inverted-index storage & search | InternalEngine, version.properties |
| Netty 4.1 | HTTP & transport I/O | modules/transport-netty4 |
| Log4j 2 | Logging | Elasticsearch.main → LogConfigurator |
| Guice | Node service wiring | NodeConstruction, org.elasticsearch.injection.guice |
| JUnit 4 + RandomizedTesting | Test runner | TESTING.asciidoc, ESTestCase |
Top-level directories
| Directory | Why it exists | Central? |
|---|---|---|
server/ | Core node: bootstrap, cluster, indices, search, REST, transport, gateway persistence | Core |
libs/ | Shared libraries extracted from server (x-content, cli, entitlement, native, plugin-api) | Core |
modules/ | Built-in plugins bundled with every distribution (painless, reindex, netty transport, repos) | Core |
x-pack/ | Commercial/licensed features: security, ML, ESQL, CCR, watcher, autoscaling, stateless | Core (when enabled) |
plugins/ | Optional installable plugins (HDFS repo, mapper extras) | Peripheral |
distribution/ | Packaging: archives, docker images, OS packages, launchers (ServerLauncher) | Build/ship |
client/ | Java low-level REST client & sniffer | API surface |
rest-api-spec/ | Machine-readable REST definitions + YAML REST tests | Contract/tests |
test/ | Shared test framework, fixtures (S3, AWS), test clusters Gradle plugin | Infra |
qa/ | Cross-module integration & packaging QA projects | Tests |
docs/ | User documentation (AsciiDoc/MDX) | Docs |
build-tools-internal/ | Gradle plugins: run task, test clusters, release | Tooling |
benchmarks/ | JMH microbenchmarks | Perf |
Entry points
| Entry | Class / script | Path |
|---|---|---|
| Production server JVM | org.elasticsearch.bootstrap.Elasticsearch#main | Elasticsearch.java |
| Process launcher (scripts) | org.elasticsearch.server.launcher.ServerLauncher | distribution/tools/server-launcher/ |
| CLI preparer | org.elasticsearch.server.cli.ServerCli | distribution/tools/server-cli/ |
| Dev run from checkout | ./gradlew run | build-tools-internal/.../elasticsearch.run.gradle |
| Plugin CLI | elasticsearch-plugin | distribution/tools/plugin-cli/ |
| REST API | RestController#dispatchRequest | HTTP :9200 default |
| Internal actions | TransportAction#execute | Registered in ActionModule |
Configuration vs generated vs tests
- Configuration:
config/elasticsearch.yml,config/jvm.options, keystore — parsed intoSettings/Environment - Generated: ESQL ANTLR parsers, entitlement policy patches, build-info, some x-pack SPI metadata
- Tests:
src/test/java(unit),src/internalClusterTest/java,src/yamlRestTest/java,src/javaRestTest/java - CI:
.buildkite/,.github/workflows/
Why server/ is the kernel
Every user operation — index, search, snapshot, cluster reroute — is implemented or orchestrated under server/src/main/java/org/elasticsearch/. Modules and x-pack plugins register handlers into the same registries (ActionModule, SearchModule, NetworkModule) during node construction. Removing server leaves no runnable node.
The libs/ split exists to share code with clients and plugin API without pulling the entire server classpath.
Module auto-discovery in Gradle
settings.gradle explicitly lists distribution and test projects, then auto-includes everything under libs/, modules/, plugins/, qa/, and x-pack/ via addSubProjects. Each subdirectory with a build.gradle becomes a Gradle subproject — which is why there are hundreds of build targets.
Continue to Main Runtime Architecture →