Hyperledger Besu node sizing: what a private network needs before you buy hardware
Sizing a private Besu network depends on three things: transaction volume, the block gas limit and the query load each node serves. Besu's system requirements documentation names these factors but does not publish a fixed hardware list, so the right machine for your network comes from your own workload profile, not from a template. Teams need this work before they issue a procurement request, before they commit to a cloud instance family or reserved capacity, and before they add RPC nodes to absorb application traffic. Each of those decisions locks in cost, and changing a disk or memory allocation after go-live is slower than getting it right at the start.
The decision is made per role, not per network. Validators take part in block production and gossip, so their load follows the transaction volume and block gas limit you configure. RPC nodes carry the JSON-RPC, PubSub and GraphQL queries that applications and integrations send, so their load follows the number and shape of those queries, which often grows faster than the chain itself. A single hardware specification copied across both roles will usually overbuild one and underbuild the other. Ask your team to write down the expected transaction rate, the gas limit you plan to set, and which applications will query each node before any vendor or cloud quote is requested.
Before buying hardware, confirm three points with your own tests or with the Besu maintainers. First, the JVM heap: by default the JVM takes 25% of system RAM, and the maximum heap is set through BESU_OPTS with -Xmx, so the memory you purchase and the memory Besu actually uses are different numbers you must set deliberately. Second, the storage type and growth rate, which you can only estimate from a rehearsal on a representative load. Third, the monitoring overhead: Prometheus needs about 3 MB of space per node per hour for Besu metrics at a 15 second scrape interval, which adds up across a fleet. Run a pilot on a non-production cluster, collect metrics with --metrics-enabled, and let the measured curves set the purchase order.
Sizing decisions and when each fits
This table compares the main sizing choices for a private Besu network: node role, host layout, JVM heap and storage type. Read each row for the condition that makes an option fit and the cost it carries. The main takeaway is that the right choice depends on your transaction volume, query load and recovery expectations, which you should measure before buying hardware.
| Decision | Option | Trade-off | When it fits |
|---|---|---|---|
| Node profile | Validator node | Carries consensus and block production, so it should not also absorb heavy query traffic | Consensus participation where RPC load is light or kept off the validator |
| Node profile | RPC node | Serves application queries and can be sized for read load, but needs its own storage and memory headroom | Applications or services that query the chain heavily |
| Host layout | Single shared host | Lowest hardware count, but one host's CPU, memory and disk contention can affect several roles at once | Development, test or a low-volume pilot where failure impact is accepted |
| Host layout | Separate host per role | More hardware and operations work, but each role's resource use and failures stay isolated | Production networks where validators must stay stable under application load |
| JVM heap | Default heap (25% of system RAM) | Requires no tuning, but the default may not match the node's workload or the memory left for the OS and metrics | Early measurement stages, before you have observed real memory use |
| JVM heap | Explicit maximum heap via BESU_OPTS and -Xmx | Gives predictable limits and a documented setting to review, but needs re-checking when load or host memory changes | Production nodes where memory limits are set from measured peaks |
| Storage | Local SSD | Typically lower latency for database access, but data is tied to one host and recovery depends on backups or resyncs | Nodes where disk latency matters and replication or backup covers host loss |
| Storage | Network-attached storage | Can simplify moving volumes between hosts, but adds latency and a shared dependency that you must test under load | Environments where storage platform standards require central storage, verified with a load test first |
How to set JVM heap for a Besu node
Set the JVM heap explicitly on every Besu validator and RPC node rather than accepting the default. By default the JVM uses 25% of system RAM as its heap, which is a sensible starting point on a shared workstation but a poor fit for a dedicated Besu host. On a machine with a large amount of memory, 25% can leave far more than the node needs unused, while on a smaller machine it may leave too little for the node's caches and query load. The maximum heap is set through BESU_OPTS with the -Xmx flag, so the value is visible in the service definition and can be reviewed under source control alongside the rest of the node configuration.
The heap is only one part of the memory a Besu process uses, and the operating system, the page cache that serves disk reads, and any sidecar processes such as log shippers or metrics exporters all need their own share of RAM. Setting -Xmx close to total memory can cause swapping or out-of-memory kills that look like node failures. Leave deliberate headroom for the operating system and co-located processes, and check that the host does not swap under load. If the node is in a container, confirm that the container memory limit and the JVM heap setting agree, since a heap larger than the container limit will be killed by the runtime.
Choose the heap value from observed usage, not from a formula. Run the same node version against a load profile that resembles your expected transaction volume and JSON-RPC traffic in a test environment, then watch heap usage and garbage collection through the metrics endpoint enabled with --metrics-enabled. Size the heap to hold the working set with margin for peaks, and repeat the test after changes to block gas limit or query patterns. Because memory use changes between Besu releases, confirm the current guidance in the JVM memory documentation for the release you deploy before you fix the value in production.
How to measure real Besu needs with Prometheus before buying hardware
This sequence turns a test network into measured CPU, memory, disk and latency figures, so hardware and heap settings follow observed load rather than guesses.
Confirm the test network and load plan
The platform team agrees which Besu version, consensus setting and node roles the test network uses, and writes down the expected transaction volume, block gas limit and the JSON-RPC, PubSub or GraphQL query mix that production nodes will serve. Besu system requirements depend on exactly these inputs, so the load plan is the baseline for every later measurement. Done when the plan is signed off and each node role on the test network matches the production topology it represents. Ask the vendor or your architect to confirm which query types are expected, since they drive memory and CPU use.
Enable metrics on every Besu node
Each validator and RPC node is started with the --metrics-enabled option, which exposes Prometheus metrics on the default endpoint port 9545. The configuration is kept under source control so that every node runs with the same metrics settings. Check that the endpoint answers locally on each host before Prometheus is involved, because a node that exposes no metrics produces no sizing data. Done when each node returns metric output on port 9545 from its own host.
Configure Prometheus scrape targets and interval
The monitoring team adds every Besu node as a scrape target in Prometheus and sets an explicit scrape interval. The Besu metrics documentation gives a reference point of about 3 MB of storage per node per hour at a 15 second scrape interval, so record the interval you choose and use that figure as the starting point for capacity planning. Done when the Prometheus targets page shows each node as up and the interval matches the one written in the plan.
Check that every scrape target is up
Before any load is applied, the engineer confirms in the Prometheus targets view that each Besu node is in the up state and that samples are arriving for CPU, memory, disk and peer metrics. A target that is down or intermittent will leave gaps in the data, so this check is repeated after any restart or network change. Done when every node has continuous samples for a full observation window with no gaps caused by scrape failures.
Run representative load on the test network
The team generates the expected transaction volume and query mix against the test network, either by replaying recorded traffic or by running a load generator that matches the plan. Run the load long enough to reach steady state, and include a period of peak activity as well as normal activity. Keep a log of when each phase starts and stops so that metrics can be aligned with the load. Done when the load log shows that the planned peak and normal phases both ran against the nodes being measured.
Collect CPU, memory, disk and latency figures
From the collected series, the engineer records CPU use and memory use per node during normal and peak phases, the JVM heap behavior, the disk growth rate per day, and the query latency for the API traffic. Disk growth is compared with the retention and pruning decisions made for the node, so the team can see whether storage will fill at the planned pace. Done when a table of peak and steady-state values per node role exists and the disk growth rate has been calculated from at least one full observation window.
Check disk growth against planned retention
The team compares the measured disk growth rate with the retention plan and with the storage they intend to buy, including headroom for the Prometheus data itself. The metrics storage figure of about 3 MB per node per hour at a 15 second scrape interval is added to the node data estimate so that the monitoring store is sized, not forgotten. Done when the projected capacity for the full retention period, for both node data and metrics, fits within the storage proposed and the assumptions are written down for review.
Set the heap from observed values
Using the peak memory figures, the engineer sets the maximum JVM heap through BESU_OPTS and the -Xmx option, rather than relying on the default of 25% of system RAM. The chosen value is applied to the test nodes and the load is repeated to confirm that the heap is neither exhausted nor so large that the host starves the operating system or other processes. Done when a repeat run at peak load completes with the chosen heap, the metrics show stable memory use, and the final values are recorded in configuration under source control.
Choosing disk type and planning storage growth
Disk decisions shape how a private Besu node performs and how long it runs before it needs more space. The cards below cover the choices that connect node performance, database growth, metrics retention and the copy you keep before an upgrade. Confirm each point against the Besu docs and your own test results before you buy storage.
Local versus network storage
Besu reads and writes its state database constantly, so the storage path matters as much as its capacity. Local SSD or NVMe attached to the node usually gives the most predictable latency for state access, while network-attached volumes add a shared failure domain and a latency floor. Ask your storage vendor for latency percentiles under write load, not only peak throughput, and test the chosen option against a realistic transaction load on your validators before committing.
IOPS and latency for state access
State reads and writes happen on the critical path of block processing and JSON-RPC queries. Heavy RPC traffic, large blocks and complex queries all raise random read demand on disk. Measure disk IOPS and latency during a load test and compare them with block processing time in your Besu metrics. If latency spikes line up with slow block imports or lagging RPC responses, storage is the likely bottleneck and more CPU or memory will not fix it.
Growth from chain data and database format
Chain data grows with every block, and its size depends on transaction volume and the database format in use. Besu's Bonsai database is the format to plan around for new networks, and its growth profile should be measured on your own chain rather than assumed. Project growth from the transaction rate you observe in a pilot, add headroom for the retention period you set, and review the projection after each release that changes the storage layout.
Separating metrics storage from node storage
Prometheus writes its own time-series data, and that data should not compete with the node database for the same disk. Besu metrics are cheap to store per node but accumulate across validators and RPC nodes over the retention window. Place the Prometheus volume on separate storage, set a retention limit that matches your audit needs, and alert when its disk fills, because a full metrics volume can quietly stop the monitoring you rely on during an incident.
Backup space before upgrades
The Bonsai database upgrades automatically on first start, and older Besu versions cannot open an upgraded database. A rollback therefore depends on a backup taken before the upgrade, so the backup volume must hold a full copy of the node data plus headroom. Size this space for every node you plan to upgrade in one window, and test restoring from the backup on a non-production node before the first real upgrade.
Confirming vendor guidance for your database
Storage guidance changes with Besu releases, database formats and the consensus you run, so the numbers in any sizing exercise need a date and a version attached. Ask the Besu maintainers or your support contact which disk types and capacities they recommend for your release, and confirm whether the guidance covers validators and RPC nodes separately. Record the answers in your sizing document so the next team can see why each volume was chosen.
Hyperledger Besu sizing questions buyers ask before hiring help
How much effort does Besu node sizing take, and what drives it?
Sizing effort depends mainly on how many node roles you run, how well your expected workload is defined, and how many environments you must measure. Requirements follow transaction volume, the block gas limit, and the number and complexity of JSON-RPC, PubSub or GraphQL queries each node serves, so a network with a single application and a light query pattern is far simpler than one with several applications polling the same RPC nodes. Validators and RPC nodes usually need separate profiles. Effort also rises when the team must test realistic load in a non-production cluster before purchasing hardware. Ask any provider to break its quote into profiling, load testing, and written sizing recommendations, and to state which node roles and environments are covered. Read the Besu system requirements page to see which inputs will be needed.
Can our own team size a Besu network without a partner?
Yes, a capable platform team can size a Besu network in-house, provided it has someone who can read JVM and node metrics and who can run realistic load. The work involves choosing CPU, memory and disk per role, setting the JVM maximum heap with -Xmx through BESU_OPTS, selecting disk type, and confirming the results under expected traffic. Teams usually struggle with the load profile rather than the arithmetic, because they must estimate query mix and transaction volume before the application exists. A partner adds value when several roles, several organizations or compliance evidence need to be covered in one exercise. Whichever route you choose, record the assumptions and the measurements so the sizing can be repeated when volume changes.
What must our team provide before sizing starts?
Your team should provide an expected transaction profile, an expected query profile, a test environment that resembles production, and read access to Prometheus for the Besu nodes. The transaction profile covers daily volume, peak bursts and the block gas limit you plan to use. The query profile lists which applications call JSON-RPC, PubSub or GraphQL, how often, and which calls are heavy. The test environment should use the same node roles, storage types and network paths you expect in production. Prometheus access matters because Besu exposes metrics when --metrics-enabled is set, with a default endpoint port of 9545, and those metrics are the basis for measuring real needs. Confirm retention and scrape settings with your monitoring owner before the measurement window opens.
How long does measuring real node needs take, and what sets that duration?
Measurement duration is set by how long you need to observe representative load, not by the tooling itself. You need enough time to capture normal traffic, peak periods and any scheduled batch activity, so the window should cover at least one full business cycle that matches your application. Prometheus storage is a practical constraint: the Besu metrics documentation estimates about 3 MB of space per node per hour at a 15 second scrape interval, so a multi-node test running for weeks needs deliberate retention planning. Other drivers include how quickly your application team can produce a realistic load generator, how many node roles are under test, and whether a change in block gas limit or query pattern forces a repeat run. Ask for the measurement plan, the window length and the criteria for accepting results in writing before work starts.
Which sizing inputs change the hardware cost most?
Cost moves most with the node role, the sustained query load and the disk type. Validators and RPC nodes place different demands on the machine, and RPC nodes that face many applications usually drive the largest CPU and memory requirements. The JVM uses 25% of system RAM by default, so the maximum heap must be set deliberately with -Xmx through BESU_OPTS rather than left to the default. Disk choice affects both performance and growth, because chain data grows over time and must be sized with headroom. Redundancy multiplies every figure, since each additional validator or RPC node repeats the cost. Ask any quote to show hardware assumptions per role, the expected growth rate, and the measurements that justify each number.
How do we request a quote for Besu sizing?
DeployOpen does not publish a price list. A quote follows from a written scope, which is agreed before work starts and is usually fixed-scope. To request one, send the number of Besu nodes and their roles, the target environment (cloud, data center or air-gapped), the expected transaction and query profile, the Prometheus setup you can share, and the deliverables you need, such as a sizing report or a recommended hardware specification. Also state whether the sizing must support compliance evidence or a multi-organization network, since those change the scope. Ask every provider to separate one-time work from any recurring retainer for re-measurement after upgrades or growth. Your quote will then reflect your actual environment rather than a generic estimate.
Should we rebuy hardware if traffic grows after go-live?
Re-measure before buying more hardware whenever transaction volume, the block gas limit or the query pattern changes materially. The Besu requirements depend on those inputs, so growth in any one of them can push a node past its planned headroom. Use Prometheus metrics from the running nodes to confirm whether CPU, memory, heap usage or disk growth is the constraint before assuming more hardware is needed. Some problems are solved by changing the query pattern or separating RPC traffic from validators, which costs less than new machines. Schedule a sizing review after each significant release or traffic change, and keep the earlier measurements so the trend is visible. Confirm the expected growth rate with your application owners before setting disk and memory budgets.
How DeployOpen scopes and delivers Besu node sizing
DeployOpen delivers Besu node sizing as a fixed-scope piece of work. Before any measurement starts, scope, deliverables and timelines are agreed in writing. For sizing, that agreement names the node roles in question (validators, RPC nodes, and any bootnodes or read-only nodes), the workloads to be measured, the infrastructure each role will run on, and the documents the client will receive. A written scope keeps the work tied to the decisions the client actually needs to make, such as whether a given host class is enough for a validator or whether RPC nodes need a separate pool. It also makes clear which items are outside the sizing exercise, such as the genesis design or the validator count, which are covered separately.
Load is measured in the client's own environment, not estimated from a template. DeployOpen works with the client's Prometheus and Grafana stack, or sets up Besu metrics collection on the test nodes with --metrics-enabled, and records CPU, memory, disk growth and peer behavior under the transaction patterns the network expects. Where a load test is needed, the client should confirm in writing who provides the traffic generator, which block gas limit is used, and what query mix the RPC nodes will face. The handover includes the sizing decisions with the measurements behind them, the chosen heap setting in BESU_OPTS, the disk type and retention assumptions, and the alert thresholds that will show when a node is outgrowing its allocation.
Ongoing support, upgrades and continuous testing are available as retainers. Sizing is not a one-time event on a permissioned network: transaction volume, state growth and new Besu releases all change the picture, so a retainer can re-run the measurements after major changes and review the heap and disk settings during each upgrade. Clients should ask for the scope, deliverables, timeline and any retainer terms in a written quote before committing. DeployOpen does not publish a price list, so the quote follows from the agreed scope.

