Optimizing system configuration
The number of possible setups is virtually unlimited, so this document cannot cover them all. Even similar builds and configurations can behave differently because of external factors. Your results may vary. Use these general guidelines as a starting point. Be cautious and make incremental changes. Test and observe each change before you move forward. Always focus on only one specific area at a time. Do not change the memory, storage, and CPU configurations all at once. Otherwise, it becomes nearly impossible to diagnose problems.Memory management
These settings in/etc/sysctl.conf can optimize memory usage and disk I/O patterns:
sudo sysctl -p.
Network stack
These settings in/etc/sysctl.conf may improve network performance:
Storage configuration
For NVMe drives, optimize I/O scheduling: Storage optimization commandsInfrastructure monitoring
Monitoring is one of the most critical components of network infrastructure. This page covers monitoring, performance tuning, and alerting configuration for Cosmos SDK and Tendermint nodes.Prometheus setup
First, install Prometheus:Grafana integration
Install and configure Grafana:Sample Grafana dashboard JSON
Sample Grafana dashboard JSON
Alert management
Install Alertmanager:Create alert rules configuration
Create alert rules configuration
Log management
Loki setup
Use Loki for log aggregation:Promtail configuration
Promtail configuration
Log rotation
Configure logrotate to manage log files:Security configuration
Network security
Configure the UFW firewall:Rate limiting
Example Nginx configuration with rate limiting
Example Nginx configuration with rate limiting
Validator-specific monitoring
Status query
Query the validator status through the SDK:Validator "status" query script
Validator "status" query script
Critical metrics
Monitor these validator-specific metrics:Backup management
Complete automated backup script
Complete automated backup script
Host system monitoring
Resource usage tracking
Install and configure node_exporter:Seed node Prometheus metrics
Since v6.7.0, seed nodes serve Prometheus metrics like other nodes. A seed serves no RPC, so its p2p metrics, such astendermint_p2p_peers, are the only way to watch it. Enable them in the [instrumentation] section of config.toml:
Metrics server limits
The metrics server uses a 10s read header timeout, a 10s read timeout, a 30s write timeout, and a 60s idle timeout.max-open-connections under [instrumentation] is not a connection limit. It caps the number of scrapes that the server handles at the same time. Requests over the cap get HTTP 503. The server does not queue them. A slow scraper holds its slot until it finishes or reaches the write timeout. 0 means no limit. The default is 3. Set the value higher than the number of scrapers that can overlap, such as an HA Prometheus pair, probes, and manual curl requests.
chain_id label on metrics
Since v6.7.0, the node adds a chain_id label to every metric that it exports. This includes the Tendermint Prometheus metrics, the Cosmos SDK telemetry, and the OpenTelemetry metrics (evmrpc_*, flatkv_*, litt_*, and pebble_*). If you already set chain_id in global-labels under [telemetry], the Cosmos SDK telemetry keeps your value.
Update PromQL that aggregates across series, such as sum(...) without (...) or by (...), to account for the new label. To scope a query to one chain, add a chain_id match.
Tendermint internal metrics
Thetendermint namespace also has these subsystems:
EVM RPC OpenTelemetry metrics
The EVM RPC layer emits OpenTelemetry metrics through the process-wideMeterProvider (for example, a Prometheus exporter). It emits these metrics in parallel with the legacy sei_* metrics, so you can migrate dashboards incrementally.
Available EVM RPC metrics
The
evmrpc_request_latency_seconds histogram carries these labels:
Migrating from legacy EVM RPC metrics
These legacysei_* metrics remain available today but are deprecated. They are scheduled for removal after dashboards migrate to the evmrpc_* OpenTelemetry metrics:
Before the legacy metrics are removed, update your Prometheus and Grafana dashboards to use the
evmrpc_* metrics. The latency unit changed from milliseconds (sei_rpc_request_latency_ms) to seconds (evmrpc_request_latency_seconds). Adjust any thresholds and panel formatting to match.
FlatKV OpenTelemetry metrics
The FlatKV state store emits OpenTelemetry metrics through the process-wideMeterProvider (for example, a Prometheus exporter). With these metrics, you can observe commit throughput, catchup progress, snapshotting, rollbacks, and snapshot imports.
Available FlatKV metrics
Labels
FlatKV metrics carry these labels where applicable:Pebble internal metrics
FlatKV turns on Pebble’s internal metrics for each data DB by default. The node does not apply anenable-pebble-metrics key from app.toml.
Pebble estimated read/write metrics
SeiDB can count estimated logical reads and writes on its PebbleDB databases. The counters are off by default. They cost less than Pebble’s full internal metrics, and you can use them to estimate read amplification (reads divided by writes).
Both counters have a
db attribute. Its value is the name of the data directory, so you can tell the FlatKV data DBs, the state store, and the receipt store apart. Turn the counters on per store in app.toml:
Log query parallelism for littidx
With the littidx receipt store, each eth_getLogs query scans several blocks at the same time. Results stay in block and transaction order. log-filter-parallelism under [receipt-store] sets how many blocks one query scans at once. The default is 16, and a value of 0 or less uses the default. The setting has no effect on pebbledb.
Per-block hash logger
The state-commit store writes a CSV file of named hashes for each block. Each row has the memIAVL module and root hashes and the FlatKV DB and root hashes. It also has the app hash, the block hash, the results hash (the next block’sLastResultsHash), and the changeset hash. To find where two nodes diverged, compare their logs with seidb hashlog compare.
The hash logger is on by default. It writes to data/hash.log under the state-commit directory, which is <home>/data/hash.log by default. With the default settings, it keeps up to 16 GiB of closed log files. Configure it in the [state-commit] section of app.toml:
If you set both
sc-hash-logger-blocks-to-retain and sc-hash-logger-max-disk-size to 0, the logs grow without limit. To turn the hash logger off:
LittDB OpenTelemetry metrics
LittDB emits its metrics through the process-wide OpenTelemetryMeterProvider instead of a private Prometheus client. If MetricsEnabled is true, LittDB records its metrics in that provider. By default (MetricsServeEndpoint = false), the application that uses LittDB exports the metrics, and LittDB does not start a /metrics server. If MetricsServeEndpoint is true, LittDB serves /metrics on MetricsPort (default 9101). LittDB no longer has the MetricsNamespace and MetricsRegistry config fields, and all metric names use a fixed litt_ prefix.
Available LittDB metrics
Attributes
Migrating from legacy LittDB metrics
The OpenTelemetry migration changed the metric names, units, and shape. You must update your existing Prometheus and Grafana dashboards:- Latency metrics moved from millisecond summaries (for example,
{namespace}_read_latency_ms) to second histograms (litt_read_latency_seconds). Change thresholds and panel formatting from milliseconds to seconds. - Counters and gauges gained a fixed
litt_prefix and explicit units. For example,bytes_readbecamelitt_bytes_read, and the cache weight gauge becamelitt_chunk_cache_weight_bytes. - The per-cache series that previously had separate metric names (for example,
chunk_read_cache_*andchunk_write_cache_*) are now the sharedlitt_chunk_cache_*metrics. Thecacheattribute distinguishes them. - The
MetricsNamespaceandMetricsRegistryconfig fields no longer exist. Metric names are fixed, and the global OTel provider always backs the metrics. Set the scrape port withMetricsPort.
Performance testing
Example benchmark script using eth_getLogs
Example benchmark script using eth_getLogs