Skip to main content

Optimizing System Configuration

There are a virtually unlimited number of unique individual setups that cannot be covered in this document. As well, even similar builds and configurations can behave differently due to external factors, so your results may vary. Here are some general guidelines to use as a starting point. Be cautious, make incremental changes, testing and observing before moving forward. Always focus on only one specific area at a time - avoid making changes to memory, storage, and CPU configs all at once. Diagnosing potential problems becomes nearly impossible otherwise.

Memory Management

The following settings in /etc/sysctl.conf can optimize memory usage and disk I/O patterns:
Apply changes: sudo sysctl -p

Network Stack

The following settings in /etc/sysctl.conf may improve network performance:

Storage Configuration

For NVMe drives, optimize I/O scheduling: Storage Optimization Commands

Infrastructure Monitoring

Monitoring is one of the most critical components of network infrastructure. performance tuning, and alerting configuration for Cosmos-SDK/Tendermint nodes.

Prometheus Setup

First, install Prometheus:
Example Prometheus configuration:

Grafana Integration

Install and configure Grafana:

Alert Management

Install Alertmanager:

Log Management

Loki Setup

Using Loki for log aggregation:

Log Rotation

Configure logrotate to manage log files:

Security Configuration

Network Security

UFW firewall configuration:

Rate Limiting

Validator-Specific Monitoring

Status Query

Query validator status through SDK:
Query through REST API:

Critical Metrics

Monitor these validator-specific metrics:

ProposerPriority Divergence Detection

Sei nodes export two Prometheus gauges that let operators detect when a validator’s ProposerPriority state diverges from the rest of the network. Divergence indicates corrupted consensus state and should be investigated immediately. Both metrics are emitted together every 1024 heights (roughly every few minutes at Sei block times). Emitting the hash as a numeric value instead of a Prometheus label keeps series cardinality constant at one series per node, rather than creating a new time series on every priority change.

How to use these metrics

Compare tendermint_state_proposer_priority_hash across your validators, but only compare samples taken at the same tendermint_state_proposer_priority_hash_height. Since the hash is only meaningful at a shared height, always pair it with the height gauge before comparing:
  • If every node reports the same hash value at the same height, their ProposerPriority state agrees.
  • If a node reports a different hash value at the same height, its ProposerPriority state has diverged and likely indicates corrupted state on that node.
Example alert rule that flags divergence across scraped nodes at a shared height:
Each checkpoint also writes a proposer priority hash checkpoint log line containing the full 32-byte hash and the packed value, which can be used for grep-based comparison across nodes.

EVM RPC Metrics

Sei nodes emit OpenTelemetry-based metrics for the EVM JSON-RPC layer through the process-wide MeterProvider (for example, a Prometheus exporter). These evmrpc_* metrics are the recommended source for monitoring RPC performance and websocket activity.
The OpenTelemetry Prometheus exporter namespace is sei_chain (underscore). When these metrics are scraped through the Prometheus exporter, exported series are prefixed accordingly (for example, sei_chain_evmrpc_request_latency_seconds, sei_chain_flatkv_commit_latency, sei_chain_app_abci_commit_duration_seconds, sei_chain_module_mid_block_duration). The metric names documented on this page are the unprefixed instrument names; prepend the sei_chain_ namespace when querying them in Prometheus/Grafana. This namespace was previously sei-chain (hyphen); because Prometheus normalizes the hyphen to an underscore anyway, existing dashboards and alert queries should continue to match, but confirm your PromQL uses the sei_chain_ prefix after upgrading.
| evmrpc_historical_debug_trace_attempts_total | counter | Number of debug_trace* requests targeting historical blocks, labeled by endpoint and connection. Incremented whenever a debug_trace* request (debug_traceTransaction, debug_traceTransactionProfile, debug_traceBlockByNumber, debug_traceBlockByHash, debug_traceCall, or debug_traceStateAccess) targets a block older than the configured maxBlockLookback. Such requests are rejected with an error like block number N is beyond max lookback of M. |

evmrpc_historical_debug_trace_attempts_total labels

evmrpc_redirected_requests_total labels

evmrpc_request_latency_seconds labels

The histogram uses the following explicit bucket boundaries (in seconds):

Legacy metric deprecation

The legacy sei_* RPC metrics — including sei_rpc_request_latency_ms and sei_websocket_connect — are still emitted alongside the new evmrpc_* metrics for backward compatibility, but they are deprecated and scheduled for removal (PLT-326) once dashboards migrate to the OpenTelemetry evmrpc_* metrics. When building or updating dashboards and alerts, prefer the evmrpc_request_latency_seconds histogram and evmrpc_websocket_connects_total counter over their legacy counterparts.

FlatKV State DB Metrics

Sei nodes emit OpenTelemetry-based metrics for the FlatKV state database through the process-wide MeterProvider (for example, a Prometheus exporter). These flatkv_* metrics let operators observe FlatKV performance and progress across commits, catchup, snapshots, rollbacks, and snapshot imports.

Latency metrics

Each latency metric is a histogram reported in seconds (unit s). Unless otherwise noted, they carry a success boolean label indicating whether the operation completed without error.

Counter metrics

Gauge metrics

The db label identifies the underlying data DB (for example, the account, storage, code, or legacy data directory), letting operators break down applied writes, pending writes, batch commits, and flush latency per DB.
Emission of Pebble’s own internal metrics is controlled separately by the FlatKV-level EnablePebbleMetrics configuration knob. When set, it overrides the per-DB EnableMetrics settings for all data DBs (account, code, storage, legacy, and metadata), so Pebble internal metrics are toggled uniformly rather than individually per DB.
Prometheus gauges are held in memory, so after a process restart these gauges reset to zero until the next emission at the following multiple of 1024 heights (up to roughly 8.5 minutes of stale or zero data). This is expected for a monitoring signal that is only consulted in response to incidents.

App (ABCI) Metrics

Sei nodes emit OpenTelemetry-based metrics for the application (ABCI) layer through the process-wide MeterProvider (for example, a Prometheus exporter). These app_* metrics let operators observe ABCI phase durations, transaction throughput and gas usage, block processing, and light invariance checks. They are the recommended source for application-level observability.
A set of legacy telemetry metrics (for example, the abci/tx/sei_lightinvariance_supply series) are still emitted alongside the new app_* metrics for backward compatibility, but they are deprecated and scheduled for removal (PLT-327) once dashboards migrate to the OpenTelemetry app_* metrics. When building or updating dashboards and alerts, prefer the app_* metrics over their legacy counterparts.

ABCI phase duration metrics

Each of these is a histogram reported in seconds (unit s), measuring the duration of the corresponding ABCI phase.

Block processing metric

The type attribute identifies the execution path: synchronous, synchronous_giga, optimistic_concurrency, or occ_giga.

Transaction counter metrics

App flow counter metrics

Light invariance metrics

Build info metric

Module & Governance Metrics

Sei nodes emit OpenTelemetry-based metrics for the SDK module lifecycle (mid-block, begin-blocker, and end-blocker execution) and for validator slash events through the process-wide MeterProvider (for example, a Prometheus exporter). These module_*, per-module *_blocker_duration, and validator_slashed metrics let operators observe where per-block module execution time is spent and track slashing activity.
These OpenTelemetry metrics are emitted alongside the existing legacy telemetry counterparts, which are retained pending verification (PLT-414). When building or updating dashboards and alerts, prefer these OpenTelemetry metrics over their legacy counterparts.

Mid-block duration metrics

Each of these is a histogram reported in seconds (unit s), measuring the duration of module mid-block execution.

Per-module begin/end-blocker duration metrics

Each of these is a histogram reported in seconds (unit s), measuring the duration of the corresponding module’s begin-blocker or end-blocker execution.

Validator slash counter

Staking keeper metrics

The staking keeper delegation metrics are emitted with a staking_keeper_ prefix to avoid collisions with other metric namespaces.
The staking keeper metrics were previously emitted without the staking_keeper_ prefix (for example, delegate, last_delegate_amount). Update any dashboards or alerts that reference the old unprefixed names.
The duration histograms use the following explicit bucket boundaries (in seconds):

Consensus Validation Metrics

Sei nodes emit an OpenTelemetry-based counter through the process-wide MeterProvider (for example, a Prometheus exporter) that tracks halting consensus validation failures swallowed by non-default ConsensusPolicy builds.
In production (default) builds this counter is always zero — every validation failure halts the node as expected. A non-zero value is only ever emitted by special-purpose binaries built with the mock_block_validation or mock_chain_validation build tags (published as sei-chain:mock_chain_validation-* and sei-chain:mock_chain_validation-nightly-* Docker images). These binaries intentionally bypass halting validation and must never be run on mainnet or any node whose state you trust; they exist for forked-state replays and similar diagnostic scenarios.
Build-tag behavior:
  • default (production) — no failures are swallowed; the counter stays at zero and every validation failure halts.
  • mock_block_validation — swallows only app_hash and data_hash failures, preserving that tag’s long-standing behavior; all other failures still halt.
  • mock_chain_validation — swallows every swallow-eligible failure except last_commit_verify (which is excluded to avoid a downstream panic and therefore still halts). Intended for forked-state replays.

sei_unsafe_validation_skipped_total kind values

Backup Management

Host System Monitoring

Resource Usage Tracking

Install and configure node_exporter:
Add to Prometheus configuration:

Performance Testing

For specific customizations or additional metrics, consult the Sei technical communities in Telegram or Discord.