Skip to content
ExponaBLOG
ELASTICSEARCH & SEARCH ENGINEERING · DAY 040 / 100

Node roles: everything engineers need to know in practice

Master, data, ingest and coordinating.

Expona Admin7 min read

Introduction

Node roles are one of the most underappreciated levers for cluster performance and stability. When you scale beyond a handful of nodes, throwing more hardware at the problem stops working—you need architectural clarity instead. Node roles: everything engineers need to know in practice means understanding how to distribute work across master, data, ingest, and coordinating nodes so your cluster remains responsive under load, recovers gracefully after failures, and doesn't waste resources on tasks that don't belong on every server.

In our experience scaling Elasticsearch across e-commerce, trading, and SaaS workloads, misconfigured node roles cause cascading performance problems that are often misdiagnosed as network or query issues. Getting this right from day one (or fixing it incrementally as you grow) is far cheaper than debugging a cluster under duress.

Why node roles matter

Elasticsearch is fundamentally a distributed system. Every node can theoretically perform every function: hold shards, coordinate search requests, manage cluster state, and run ingest pipelines. But when you have 50 or 500 nodes, this one-size-fits-all approach breaks down.

Different workloads consume different resources. Cluster coordination is CPU-bound and needs stable memory; data indexing and search are I/O and heap-intensive; ingest pipeline execution can spike unpredictably. By segregating roles, you isolate failure domains, tune hardware per purpose, and scale each tier independently. A dedicated master node doesn't compete with data indexing for JVM heap. A coordinating node doesn't waste disk on shard replicas it will never hold.

Dedicated master nodes for large clusters

Master-eligible nodes manage cluster state: which shards live where, which nodes are alive, shard allocation decisions, and index metadata. In small clusters (under 10 nodes), any node can be master-eligible. But as you grow, this responsibility becomes a bottleneck.

Master elections require quorum voting. If a data node is deep in a garbage collection pause during an election, the cluster pauses with it. If you're reindexing terabytes of data on your master-eligible node, it may drop out of the quorum. Dedicated masters separate this critical function from I/O storms and heap pressure.

When to use dedicated masters:

  • Clusters with more than 10 data nodes
  • High-volume ingest pipelines
  • Frequent index creation or deletion
  • Strict SLA requirements for cluster stability

In practice, run an odd number of master-eligible nodes (3, 5, or 7) with no data or ingest roles. This guarantees quorum tolerance even if one node fails. A 3-node master quorum can lose one node and still function. A single master or 2-node setup loses quorum if one master drops.

Configuration example:

json
{
  "node.roles": ["master"],
  "cluster.voting_only": false,
  "discovery.seed_hosts": ["master-1", "master-2", "master-3"],
  "cluster.initial_master_nodes": ["master-1", "master-2", "master-3"]
}

Master nodes should be modest in size: 8–16 GB heap, 4–8 cores, and local SSD for cluster state snapshots. They don't need the storage or networking bandwidth of data nodes. The bottleneck is CPU and GC stability, not throughput.

Data nodes hold shards

Data nodes are where your indices live. Every shard replica is stored on at least one data node. When you search, data nodes execute search logic locally and return results. When you index, data nodes persist documents and manage inverted indices.

Data nodes are the workhorses. They need the most resources: heap, CPU, disk I/O, and network bandwidth. In large clusters, it's common to have dozens or hundreds of data nodes while keeping master, ingest, and coordinating roles separate.

Scaling data nodes horizontally:

When your cluster grows beyond capacity, the first lever is horizontal scaling: add more data nodes. Elasticsearch automatically rebalances shards across new nodes. This spreads I/O, memory, and CPU load. In a trading system handling millions of intraday events, adding five data nodes cuts per-node load by a factor of five—assuming your shard distribution is healthy.

Configuration example:

json
{
  "node.roles": ["data"],
  "node.attr.data_tier": "hot",
  "discovery.seed_hosts": ["master-1", "master-2", "master-3"],
  "cluster.voting_only": false
}

Data nodes should not be master-eligible (unless your cluster is very small). This prevents data nodes from being elected master during elections or cluster recovery, which would stall indexing.

Sizing data nodes:

  • Heap: 30–50% of physical RAM (e.g., 16 GB heap on a 64 GB box). Never exceed 31 GB to stay below JVM compressed object pointer threshold.
  • Cores: 8–16, depending on query complexity. Search is CPU-hungry; indexing is I/O-bound.
  • Disk: 3–5 TB per node (NVMe preferred). Monitor disk utilization; stay below 80% full.
  • Network: 1 Gbps minimum; 10 Gbps if you're in the cloud with high per-node throughput.

Ingest nodes run pipelines

Ingest pipelines transform documents before indexing. A pipeline might parse a JSON payload, enrich it with geolocation data, hash a field, or split a comma-separated string. Running these transformations on every document can consume significant CPU and temporary memory.

By default, every node can run ingest pipelines. But if you send a bulk index request with a heavy pipeline to a data node already performing searches, you're starving search for CPU. Dedicated ingest nodes isolate pipeline execution from query workloads.

Real-world scenario:

In an e-commerce platform, incoming purchase events go through a pipeline that looks up SKU metadata, calculates shipping cost, and enriches with customer tier. That pipeline CPU cost is fixed per document. Running it on data nodes (which also handle searches) creates contention. Routing ingest traffic through dedicated ingest nodes means data nodes focus on search and baseline indexing, while ingest nodes handle pipeline overhead.

Configuration example for ingest node:

json
{
  "node.roles": ["ingest"],
  "discovery.seed_hosts": ["master-1", "master-2", "master-3"],
  "cluster.voting_only": false
}

Configuration example for data node without ingest:

json
{
  "node.roles": ["data"],
  "node.ingest": false,
  "discovery.seed_hosts": ["master-1", "master-2", "master-3"],
  "cluster.voting_only": false
}

Not every cluster needs dedicated ingest nodes. If your pipelines are simple or ingest volume is low, collocating ingest with data is fine. But for high-throughput systems or CPU-intensive transformations, isolate ingest nodes and scale them independently. Start with 2–3 ingest nodes; scale horizontally if ingest latency exceeds SLA.

Coordinating nodes route requests

Coordinating nodes (sometimes called client nodes) do not hold data, do not manage cluster state, and do not run ingest pipelines. They receive search or bulk requests, determine which data nodes hold relevant shards, forward queries to those nodes, and aggregate results back to the client.

Coordinating nodes are pure routers and aggregators. They're lightweight in disk and state management but CPU-intensive during aggregation (especially for complex aggregations across thousands of shards).

When coordinating nodes shine:

  • High-volume API gateways: Thousands of concurrent HTTP clients. Coordinating nodes buffer requests and fan them out efficiently.
  • Complex aggregations: When you're computing percentiles, cardinality, or date histograms across a massive dataset, coordinating nodes gather results from hundreds of shards and merge them. This work is CPU-bound and I/O-light.
  • Multi-tenant isolation: Route tenant A queries to coordinating nodes, which only query indices A owns. Data nodes aren't bothered with cross-tenant logic.
  • Application server pattern: Elasticsearch is your backend, application servers are your frontend. Coordinating nodes live in the application tier or as a separate Elasticsearch frontend layer.

Configuration example:

json
{
  "node.roles": [],
  "discovery.seed_hosts": ["master-1", "master-2", "master-3"],
  "cluster.voting_only": false
}

An empty node.roles array creates a coordinating-only node. Coordinating nodes can be deployed close to application servers or load balancers. They're stateless (no persistent data) so can scale and restart freely.

Common mistakes

Mistake 1: Master-eligible data nodes in large clusters. If you have 30 data nodes all set as master-eligible, cluster elections become unpredictable. A data node indexing at peak throughput may GC and miss the election, causing unnecessary failovers. Separate master and data roles above 10 nodes.

Mistake 2: Under-sizing master nodes. Masters are often provisioned with minimal resources because they don't hold data. But cluster state management under rapid shard churn (heavy reindexing, rolling updates) is CPU-bound. Undersized masters become a bottleneck during cluster recovery. Allocate 8–16 cores and 8–16 GB heap even for a small master cluster.

Mistake 3: Collocating ingest and search on overloaded data nodes. A 100-node cluster with heavy ingest pipelines and heavy search workload should separate ingest. If you see coordinating node CPU at 30% and data node CPU at 80%, check whether ingest is consuming data node resources. Split ingest into its own tier and scale independently.

Mistake 4: Coordinating nodes that are too small. A single small coordinating node can be a bottleneck for aggregation. If you have 50 data nodes and one coordinating node, the coordinator is fanning out to 50 nodes and gathering results sequentially. Add more coordinating nodes or increase cores on the existing coordinator. Unlike data nodes, coordinating nodes are cheap to add since they hold no state.

Mistake 5: Forgetting to disable roles explicitly. If you want a data-only node, set "node.roles": ["data"] and "node.ingest": false. Don't rely on defaults. Defaults change between versions and can silently enable ingest or master-eligibility when you don't expect it.

Key takeaways

  • Dedicated master nodes are essential above 10 data nodes. Run 3, 5, or 7 odd-numbered masters to guarantee quorum tolerance.
  • Data nodes are your workhorses and scale horizontally. Size them for heap (30–50% of RAM), cores (8–16), and disk capacity (3–5 TB).
  • Ingest nodes isolate pipeline CPU from search and indexing. Use them for high-volume or CPU-intensive transformations.
  • Coordinating nodes are stateless routers that aggregate results. Deploy them for high-concurrency APIs or complex aggregations.
  • Set node roles explicitly in configuration. Never assume defaults; always declare node.roles and node.ingest.
  • Monitor role-specific metrics: master CPU and cluster state latency, data node disk and GC, ingest node pipeline latency, coordinating node aggregation time.
  • Scale each role independently. Adding a data node doesn't improve ingest throughput; adding an ingest node doesn't improve search latency on its own.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles