Skip to main content

Teku 25.12.0 vs 26.2.0 vs 26.3.0: Cross-version resource & performance analysis

· 10 min read
Stefan Kobrc
Founder RockLogic

A deep dive into how Teku evolved across three releases: the RocksDB migration in 26.2.0, jemalloc in 26.3.0, and what both changes mean for CPU, memory, GC overhead, disk I/O, and block import latency on real hardware.

Teku 25.12.0 vs 26.2.0 vs 26.3.0: Cross-version resource & performance analysis

Overview

We compared three Teku consensus client versions on our NDC2 bare-metal fleet in Vienna, each paired with all 6 execution clients (Besu, Erigon, Ethrex, Geth, Nethermind, Reth). Each version was measured over a 14-day window during its active deployment period using avg_over_time(...[14d:1h]) instant queries against our Prometheus-cold datasource.

VersionRelease DateMeasurement WindowKey Changes
25.12.0Dec 16, 2025Jan 15 – Jan 29, 2026Late block reorg, block building prep, sidecar recovery
26.2.0Feb 11, 2026Feb 15 – Mar 1, 2026RocksDB as default DB, DAS backfiller, getBlobs API
26.3.0Mar 5, 2026Mar 15 – Mar 29, 2026jemalloc allocator, SSZ serialization fix, partial sidecar import

The full report is available as a PDF download at the bottom of this post.

Fleet-level headline numbers

The two architectural changes — LevelDB → RocksDB in 26.2.0 and the jemalloc memory allocator in 26.3.0 — drove the majority of the performance shifts:

Fleet-wide changes from Teku 25.12.0 to 26.3.0

Metric25.12.0 → 26.3.0What happened
CPU usage−44%RocksDB caching + jemalloc reducing GC-driven CPU spikes
GC overhead−36%jemalloc reduced heap fragmentation → fewer full GC cycles
Disk reads (host)−79%RocksDB block cache eliminates most disk reads
Disk writes (host)−61%LSM-tree architecture writes more efficiently than LevelDB
Block import delay−24%Fastest average: 297ms in 26.3.0
RSS memory+2.8%RocksDB uses more in-memory structures (peaked at +5.5% in 26.2.0, recovered)
Open file descriptors+101%Expected: RocksDB holds many SST files open
Peer count (libp2p)+9%Steady improvement across versions

CPU utilization

Metric: rate(process_cpu_seconds_total{job="teku"}[5m]) — Teku JVM process CPU in CPU-seconds per second.

Teku CPU usage by EC pairing across three versions

EC Pairing25.12.026.2.026.3.0Δ 25.12→26.2Δ 26.2→26.3
Besu0.7610.4410.431🟢 −42%🟢 −2%
Erigon0.7040.4140.409🟢 −41%🟢 −1%
Ethrex0.5940.5520.419🟢 −7%🟢 −24%
Geth0.7710.5530.429🟢 −28%🟢 −22%
Nethermind0.7200.3300.305🟢 −54%🟢 −8%
Reth0.7220.3640.377🟢 −50%🟠 +4%
Fleet Average0.7120.4420.395🟢 −38%🟢 −11%

CPU dropped 38% from 25.12.0 to 26.2.0. RocksDB's block cache and bloom filters reduce per-lookup processing compared to LevelDB. Version 26.3.0 added another 11% reduction through jemalloc's more efficient allocation patterns reducing GC-driven CPU spikes. The Nethermind pairing consistently shows the lowest Teku CPU usage across all three versions.

Memory & JVM analysis

RSS and JVM heap memory across three versions

Process RSS memory

Metric: process_resident_memory_bytes{job="teku"} — total physical memory consumed by the Teku JVM process.

EC Pairing25.12.0 (GB)26.2.0 (GB)26.3.0 (GB)Δ 25.12→26.3
Besu8.679.439.20🟠 +6.2%
Erigon9.109.319.16⚪ +0.6%
Ethrex8.749.489.20🟠 +5.3%
Geth9.039.509.10⚪ +0.7%
Nethermind9.079.349.13⚪ +0.6%
Reth8.909.399.20🟠 +3.4%
Fleet Average8.929.419.16🟠 +2.8%

RSS peaked in 26.2.0 (+5.5% vs 25.12.0), consistent with RocksDB's larger in-memory structures (block cache, memtables, bloom filters). Version 26.3.0 clawed back roughly half through jemalloc's reduced memory fragmentation, leaving a net +2.8%.

JVM heap memory

Metric: jvm_memory_used_bytes{area="heap"} — Java heap utilization.

EC Pairing25.12.0 (GB)26.2.0 (GB)26.3.0 (GB)Δ 25.12→26.3
Besu5.335.735.99🟠 +12.3%
Erigon5.765.705.82⚪ +1.0%
Ethrex5.895.776.05🟠 +2.7%
Geth5.386.146.05🟠 +12.3%
Nethermind5.366.016.16🟠 +15.0%
Reth5.325.786.15🟠 +15.5%
Fleet Average5.515.856.04🟠 +9.6%

Heap grew steadily, reflecting increased in-heap state caching from the RocksDB JNI bridge and the natural growth of Ethereum's state tree. All values remain well within Teku's default 8 GB max heap.

JVM native memory

VersionFleet Avg (MB)Delta
25.12.0705
26.2.0739🟠 +4.8%
26.3.0736⚪ −0.4%

Native (off-heap) memory rose modestly with RocksDB and stabilized with jemalloc.

JVM garbage collection

Metric: rate(jvm_gc_collection_seconds_sum[5m]) — fraction of time spent in GC per second. This is a critical Teku-specific metric because GC pauses directly impact block processing latency.

GC overhead by EC pairing across three versions

EC Pairing25.12.0 (ms/s)26.2.0 (ms/s)26.3.0 (ms/s)Δ 25.12→26.3
Besu2.772.821.90🟢 −31%
Erigon1.593.012.29🔴 +44%
Ethrex2.853.871.58🟢 −45%
Geth3.293.011.60🟢 −51%
Nethermind3.152.141.73🟢 −45%
Reth2.832.341.47🟢 −48%
Fleet Average2.752.871.76🟢 −36%

GC overhead was flat from 25.12.0 to 26.2.0. The introduction of jemalloc in 26.3.0 is the standout: fleet-wide GC time dropped 36%. jemalloc reduces heap fragmentation, meaning fewer large-object promotions to old gen and fewer full GC cycles. For a Java client like Teku, this matters directly — GC pauses are a primary contributor to block import latency.

note

The Erigon pairing shows an anomalous GC increase across all versions. This may reflect interaction effects with Erigon's execution response patterns rather than a Teku-internal issue.

Storage engine & disk I/O

Host-level disk I/O

Metrics: rate(node_disk_read_bytes_total[5m]) and rate(node_disk_written_bytes_total[5m]) — host-level metrics that include both Teku CC and its paired EC. Since EC versions didn't change across measurement windows, deltas are attributable to the Teku version change.

Disk read and write rates across three versions

EC PairingRead 25.12Read 26.2Read 26.3Write 25.12Write 26.2Write 26.3
Besu2,6254833906,0401,3051,272
Erigon4244703501,1411,2821,294
Ethrex1,1276033922,1431,8881,303
Geth1,5287102593,1722,0031,227
Nethermind1,4892201862,5831,1451,304
Reth1,9163262834,4681,2431,220
Fleet Avg1,5184693103,2581,4781,270

All values in KB/s.

Read throughput dropped 79% (1,518 → 310 KB/s) and write throughput fell 61% (3,258 → 1,270 KB/s). RocksDB's block cache and SST-based design is far more read-efficient than LevelDB. The Besu pairing saw the most dramatic read improvement (−85%).

RocksDB internal metrics (26.2.0+ only)

These metrics are only available for versions using RocksDB. Version 25.12.0 ran LevelDB which does not expose equivalent counters.

Metric26.2.0 Fleet Avg26.3.0 Fleet AvgDelta
storage_bytes_read rate (KB/s)84.3103.6🟠 +23%
storage_bytes_written rate (MB/s)1.531.35🟢 −12%
storage_compact_write_bytes rate (KB/s)543.5484.0🟢 −11%

Write amplification improved in 26.3.0: both raw write rate and compaction writes decreased ~11%. The slight read increase likely reflects the partial sidecar import feature doing more background reads.

Block import performance

Metric: beacon_block_import_delay_latest — most recent block import delay in milliseconds. This captures end-to-end latency from receiving a block to completing its import into the beacon state.

Block import delay by EC pairing across three versions

EC Pairing25.12.0 (ms)26.2.0 (ms)26.3.0 (ms)Δ 25.12→26.3
Besu268482221🟢 −18%
Erigon519490347🟢 −33%
Ethrex772303209🟢 −73%
Geth251319209🟢 −17%
Nethermind239513444🔴 +86%
Reth284426352🔴 +24%
Fleet Average389422297🟢 −24%

Version 26.2.0 was slightly slower fleet-wide — likely early-stage RocksDB tuning and the concurrent DAS backfiller adding load. Version 26.3.0 brought a strong recovery, achieving the lowest fleet-wide latency at 297 ms. The Ethrex pairing improved most dramatically (−73%), while the Nethermind pairing shows persistently elevated import times that warrant EC-side investigation.

Operator impact

Lower block import delay means attestations can be created sooner after a block arrives, directly improving validator effectiveness and reducing inclusion delay.

P2P networking & peer connectivity

Peer connectivity metrics across three versions

Metric25.12.026.2.026.3.0Trend
beacon_peer_count (fleet avg)44.945.949.5🟢 +10%
libp2p_peers (fleet avg)90.891.998.9🟢 +9%
discovery_live_nodes (fleet avg)160.7168.4176.4🟢 +10%
Gossip rate (msg/s, fleet avg)6.235.997.85🟢 +26%

All peer metrics improved steadily. Discovery live nodes grew from ~161 to ~176, suggesting the Discv5 layer is maintaining more active ENR records. Gossip throughput peaked in 26.3.0 — consistent with faster block processing enabling quicker re-gossip.

Data availability sampling (DAS) & PeerDAS

Metric: rate(beacon_data_column_sidecar_processing_requests_total[5m]) — DAS workload rate.

DAS sidecar processing rate by EC pairing

DAS processing rates show significant per-pairing variance. The zero values in 25.12.0 for Erigon/Ethrex reflect sync issues that resolved in later versions. Version 26.3.0 allows nodes with >50% custody requirements to begin importing blocks after downloading only 50% of sidecars — an architectural improvement that doesn't compromise data availability guarantees.

Open file descriptors — the trade-off

Open file descriptors by EC pairing across three versions

EC Pairing25.12.026.2.026.3.0Δ 25.12→26.3
Besu4809571,329🔴 +177%
Erigon7809311,375🔴 +76%
Ethrex8011,0311,299🔴 +62%
Geth6439391,319🔴 +105%
Nethermind6827511,245🔴 +83%
Reth5277871,279🔴 +143%
Fleet Average6528991,308🔴 +101%

File descriptors doubled — the most visible trade-off of RocksDB. Its LSM-tree architecture holds many SST files open simultaneously for efficient reads. Growth continued from 26.2.0 to 26.3.0 as databases accumulated more SST files through compaction.

Operator action required

Ensure ulimit -n is set to at least 65536 on hosts running Teku 26.x. The default 1024 on many Linux distributions will cause failures. Docker containers should pass --ulimit nofile=65536:65536.

Summary & recommendations

Dimension25.12.026.2.026.3.0
CPU EfficiencyBaseline🟢 Major improvement🟢 Best
Memory Footprint🟢 Lowest🟠 +5.5%🟠 +2.8% (recovering)
GC OverheadBaseline⚪ Similar🟢 Best (−36%)
Disk I/O🔴 Highest🟢 Major improvement🟢 Best
Block Import SpeedModerate🟠 Slight regression🟢 Best (297ms)
Peer ConnectivityGoodGood🟢 Best
File Descriptors🟢 Lowest🟠 +38%🔴 +101% (monitor)
Storage BackendLevelDBRocksDBRocksDB + jemalloc
Stability🟢 Stable🟢 Stable🟢 Mandatory (SSZ fix)

Key takeaways

  1. Upgrade to 26.3.0 is mandatory. Beyond the SSZ serialization bug fix, 26.3.0 delivers the best performance profile across nearly every dimension.

  2. Verify file descriptor limits. With 26.3.0 averaging 1,308 open FDs (and likely higher under peak load), ensure systems allow at least 65,536 file descriptors.

  3. Monitor RocksDB compaction. Add storage_compact_write_bytes and storage_bytes_written to your dashboards. Abnormal compaction spikes can indicate database health issues.

  4. Consider DAS backfiller tuning. If 26.x nodes show elevated CPU during backfill, --Xp2p-reworked-sidecar-custody-sync-batch-size=1 can throttle the backfiller.

  5. Watch the Nethermind pairing. Block import delays are persistently higher with Nethermind across 26.x versions — this warrants investigation on the EL side.

Download the full report

The complete analysis with additional detail on JVM thread pools, executor queue depths, and RocksDB internal counters is available as a styled PDF:

📄 Download full report (PDF)

Methodology notes

All data sourced from the prometheus-cold datasource (Org 6) in the StereumLabs Grafana instance. Query pattern: avg by (ec_client) (avg_over_time(metric{cc_client="teku", cc_version="...", role="cc", job="teku"}[14d:1h])) evaluated as instant queries at the end of each 14-day window. Rate metrics use rate(...[5m]) inside the subquery. Host-level metrics filtered with device!~"lo|veth.*|docker.*|br.*" to exclude virtual interfaces. All nodes run on NDC2 bare-metal (Vienna), eliminating cloud noise.

For details on our label conventions and how to build your own dashboards against our data, see Build your own dashboards.