Elasticsearch — Architecture

Runtime components, entry points, lifecycle

3. Main runtime architecture

Runtime components

ComponentClassResponsibility
Node shellNodeLifecycle of all services; holds Guice Injector
Cluster serviceClusterServiceFacade over master + applier threads
Master pathMasterServiceSerializes cluster-state update tasks on elected master
Follower pathClusterApplierServiceApplies published cluster state locally
Election & publishCoordinatorLeader election, state publication, commit
TransportTransportServiceInter-node RPC; action routing
HTTPHttpServerTransportREST listener (Netty implementation in module)
IndicesIndicesServiceCreates/removes IndexService / IndexShard
ShardIndexShardPer-shard indexing, search, recovery, engine
EngineInternalEngineLucene + translog + seq_no logic
AllocationAllocationServiceDecides shard placement; invoked via reroute tasks
GatewayGatewayMetaStatePersists/recovers cluster metadata on disk
Thread poolsThreadPoolwrite, search, management, generic, etc.

Core abstractions

Startup lifecycle

bin/elasticsearch → ServerLauncher (CLI JVM) → ServerCli preparer (settings, keystore, JVM args) → Elasticsearch.main (server JVM) initPhase1: Environment, logging, ServerArgs initPhase2: natives, JarHell, plugins, entitlements initPhase3: new Node(...); node.start() plugin LifecycleComponents.start() IndicesService.start() TransportService.start() GatewayMetaState.start() ← load persisted metadata BootstrapChecks (if HTTP about to open) Coordinator.start() ClusterService.start() Coordinator.startInitialJoin() [wait for master if configured] HttpServerTransport.start() sendCliMarker(SERVER_READY) main() returns; keep-alive thread holds JVM
Node.start() ordering (evidence)

Node.start() deliberately starts transport before HTTP, runs gateway metadata recovery, validates bootstrap checks, then joins the cluster and only then binds REST. HTTP starts last so clients cannot hit a half-initialized node.

NodeConstruction — the wiring diagram

NodeConstruction.prepareConstruction() is the composition root: loads plugins, builds SettingsModule, NetworkModule, ClusterModule, IndicesModule, ActionModule, creates Guice injector, returns a NodeConstruction handle consumed by Node's constructor.

Key side effect: every TransportAction and REST handler is registered here; missing registration → action not found at runtime.

NodeConstruction.java

Control flow vs data flow

CONTROL (cluster metadata): REST/admin API → TransportMasterNodeAction → MasterService task queue → executor mutates ClusterState → Coordinator.publish → all nodes ClusterApplierService.applyChanges → IndicesClusterStateService creates/drops shards DATA (documents): REST bulk/index → TransportBulkAction → per-shard TransportShardBulkAction → IndexShard → InternalEngine → Lucene IndexWriter + Translog → replication to replica shards (TransportReplicationAction) DATA (search): REST search → TransportSearchAction (coordinator) → SearchTransportService → SearchService.executeQueryPhase → QueryPhase / FetchPhase → merge SearchResponse

External systems

SystemIntegration point
Local filesystemNodeEnvironment — data, logs, shard stores
Remote object storesRepositoryPlugin — S3/GCS/Azure modules
LDAP/OIDC/SAMLx-pack security realm plugins
KibanaHTTP consumer; system indices (kibana module)
Apache Kafka / BeatsIngest pipelines, Elastic Agent (outside this repo)
Cloud orchestrationAutoscaling x-pack plugin; ESS docker exports in distribution
ML modelsx-pack ML plugin; inference ingest processors

Plugin and module system

Built-in modules/ are plugins loaded from modules/ directory in the distribution. Optional plugins install under plugins/. PluginsLoader scans JARs, validates entitlements, instantiates Plugin subclasses.

Plugin hooks used everywhere:

Plugin.java

Overview · Execution Flows →