> ## Documentation Index
> Fetch the complete documentation index at: https://seilabs-docs-retire-ibc-tokenfactory-guides.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Sei Node Advanced Configuration & Monitoring

> Optimize your Sei node's performance with advanced system configurations, monitoring setup with Prometheus and Grafana, and effective alerting strategies for maintaining reliable node operations.

## 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:

```bash theme={"dark"}
# Minimize swapping
vm.swappiness = 1

# Control disk write behavior
vm.dirty_background_ratio = 3
vm.dirty_ratio = 10
vm.dirty_expire_centisecs = 300
vm.dirty_writeback_centisecs = 100
```

Apply changes: `sudo sysctl -p`

### Network Stack

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

```bash theme={"dark"}
# Increase connection handling capacity
net.core.somaxconn = 32768
net.core.netdev_max_backlog = 32768
net.ipv4.tcp_max_syn_backlog = 16384

# Optimize buffer sizes
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 87380 16777216
```

### Storage Configuration

For NVMe drives, optimize I/O scheduling:

Storage Optimization Commands

```bash theme={"dark"}
# Set IO scheduler
echo "none" > /sys/block/nvme0n1/queue/scheduler

# Set read-ahead buffer
blockdev --setra 4096 /dev/nvme0n1

# Set IO priority in systemd service
sudo tee -a /etc/systemd/system/seid.service << EOF
[Service]
IOSchedulingClass=realtime
IOSchedulingPriority=2
EOF

# Configure disk mount options
sudo tee -a /etc/fstab << EOF
/dev/nvme0n1p1 /data ext4 defaults,noatime,nosuid,nodev,noexec,commit=60 0 0
EOF
```

## 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:

```bash theme={"dark"}
wget https://github.com/prometheus/prometheus/releases/download/v2.42.0/prometheus-2.42.0.linux-amd64.tar.gz
tar xvf prometheus-2.42.0.linux-amd64.tar.gz
```

Example Prometheus configuration:

```yaml theme={"dark"}
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'sei_node'
    static_configs:
      - targets: ['node1_ip:port']
    metrics_path: /metrics
  - job_name: 'node'
    static_configs:
      - targets: ['node2_ip:port']
```

### Grafana Integration

Install and configure Grafana:

```bash theme={"dark"}
sudo apt install -y apt-transport-https software-properties-common
sudo add-apt-repository "deb https://packages.grafana.com/oss/deb stable main"
sudo apt update && sudo apt-get install grafana
```

<Accordion title="Sample Grafana Dashboard JSON">
  ```json theme={"dark"}
  {
  	"annotations": {
  		"list": [
  			{
  				"builtIn": 1,
  				"datasource": "-- Grafana --",
  				"enable": true,
  				"hide": true,
  				"iconColor": "rgba(0, 211, 255, 1)",
  				"name": "Annotations & Alerts",
  				"type": "dashboard"
  			}
  		]
  	},
  	"editable": true,
  	"gnetId": null,
  	"graphTooltip": 0,
  	"id": 1,
  	"links": [],
  	"panels": [
  		{
  			"alerting": {},
  			"aliasColors": {},
  			"bars": false,
  			"dashLength": 10,
  			"dashes": false,
  			"datasource": null,
  			"fieldConfig": {
  				"defaults": {
  					"custom": {}
  				},
  				"overrides": []
  			},
  			"fill": 1,
  			"fillGradient": 0,
  			"gridPos": {
  				"h": 8,
  				"w": 12,
  				"x": 0,
  				"y": 0
  			},
  			"hiddenSeries": false,
  			"id": 2,
  			"legend": {
  				"avg": false,
  				"current": false,
  				"max": false,
  				"min": false,
  				"show": true,
  				"total": false,
  				"values": false
  			},
  			"lines": true,
  			"linewidth": 1,
  			"nullPointMode": "null",
  			"options": {
  				"alertThreshold": true
  			},
  			"percentage": false,
  			"pluginVersion": "7.2.0",
  			"pointradius": 2,
  			"points": false,
  			"renderer": "flot",
  			"seriesOverrides": [],
  			"spaceLength": 10,
  			"stack": false,
  			"steppedLine": false,
  			"targets": [
  				{
  					"expr": "tendermint_consensus_height",
  					"interval": "",
  					"legendFormat": "",
  					"refId": "A"
  				}
  			],
  			"thresholds": [],
  			"timeRegions": [],
  			"title": "Block Height",
  			"tooltip": {
  				"shared": true,
  				"sort": 0,
  				"value_type": "individual"
  			},
  			"type": "graph",
  			"xaxis": {
  				"buckets": null,
  				"mode": "time",
  				"name": null,
  				"show": true,
  				"values": []
  			},
  			"yaxes": [
  				{
  					"format": "short",
  					"label": null,
  					"logBase": 1,
  					"max": null,
  					"min": null,
  					"show": true
  				},
  				{
  					"format": "short",
  					"label": null,
  					"logBase": 1,
  					"max": null,
  					"min": null,
  					"show": true
  				}
  			],
  			"yaxis": {
  				"align": false,
  				"alignLevel": null
  			}
  		}
  	],
  	"schemaVersion": 26,
  	"style": "dark",
  	"tags": [],
  	"templating": {
  		"list": []
  	},
  	"time": {
  		"from": "now-6h",
  		"to": "now"
  	},
  	"timepicker": {},
  	"timezone": "",
  	"title": "Sei Node Metrics",
  	"uid": "sei_metrics",
  	"version": 1
  }
  ```
</Accordion>

### Alert Management

Install Alertmanager:

```bash theme={"dark"}
wget https://github.com/prometheus/alertmanager/releases/download/v0.25.0/alertmanager-0.25.0.linux-amd64.tar.gz
tar xvf alertmanager-0.25.0.linux-amd64.tar.gz
```

<Accordion title="Create Alert Rules Configuration">
  ```yaml theme={"dark"}
  groups:
    - name: validator_alerts
      rules:
        - alert: NodeDown
          expr: up == 0
          for: 5m
          labels:
            severity: critical
          annotations:
            summary: 'Node {{ $labels.instance }} down'

        - alert: BlockProductionSlow
          expr: rate(tendermint_consensus_height[5m]) < 0.1
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: 'Block production is slow on {{ $labels.instance }}'
        - alert: ValidatorMissedBlocks
          expr: increase(tendermint_consensus_validator_missed_blocks[1h]) > 0
          labels:
            severity: critical
          annotations:
            summary: 'Validator missing blocks'

        - alert: ValidatorJailed
          expr: tendermint_consensus_validator_status == 0
          labels:
            severity: critical
          annotations:
            summary: 'Validator has been jailed'

        - alert: ConsensusStalled
          expr: tendermint_consensus_height_status == 0
          for: 5m
          labels:
            severity: critical
          annotations:
            summary: 'Consensus has stalled'
  ```
</Accordion>

## Log Management

### Loki Setup

Using Loki for log aggregation:

```bash theme={"dark"}
wget https://github.com/grafana/loki/releases/download/v2.8.0/loki-linux-amd64.zip
unzip loki-linux-amd64.zip
```

<Accordion title="Promtail Configuration">
  ```yaml theme={"dark"}
  server:
    http_listen_port: 9080

  positions:
    filename: /tmp/positions.yaml

  clients:
    - url: http://localhost:3100/loki/api/v1/push

  scrape_configs:
    - job_name: sei_logs
      static_configs:
        - targets:
            - localhost
          labels:
            job: seid_logs
            __path__: /var/log/seid/*.log
  ```
</Accordion>

### Log Rotation

Configure logrotate to manage log files:

```bash theme={"dark"}
sudo tee /etc/logrotate.d/sei << EOF
/var/log/sei/*.log {
    daily
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 sei sei
    sharedscripts
    postrotate
        systemctl reload seid
    endscript
}
EOF
```

## Security Configuration

### Network Security

UFW firewall configuration:

```bash theme={"dark"}
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 26656/tcp comment 'Sei P2P'
sudo ufw allow 26657/tcp comment 'Sei RPC'
sudo ufw allow 9090/tcp comment 'Sei gRPC'
sudo ufw enable
```

### Rate Limiting

<Accordion title="Example Nginx Configuration with Rate Limiting">
  ```nginx theme={"dark"}
  http {
      limit_req_zone $binary_remote_addr zone=sei_rpc:10m rate=10r/s;

      server {
          listen 26657;
          location / {
              limit_req zone=sei_rpc burst=20 nodelay;
              proxy_pass http://localhost:26657;
          }
      }
  }
  ```
</Accordion>

## Validator-Specific Monitoring

### Status Query

Query validator status through SDK:

```bash theme={"dark"}
seid query staking validator $(seid keys show --bech val -a <validator_keyfile_name>)
```

Query through REST API:

```sh theme={"dark"}
curl -s "http://localhost:1317/cosmos/staking/v1beta1/validators/<valoper_address>"
```

<Accordion title="Validator &#x22;Status&#x22; Query Script">
  ```sh theme={"dark"}
  #!/bin/bash

  MONIKER="$1"
  API_URL="http://localhost:1317/cosmos/staking/v1beta1/validators?pagination.limit=500"

  echo "Querying validators from $API_URL..."

  VALIDATOR_DATA=$(curl -s "$API_URL" | jq -c --arg MONIKER "$MONIKER" '.validators[] | select(.description.moniker == $MONIKER)')

  if [[ -z "$VALIDATOR_DATA" ]]; then
      echo "❌ No validator found with moniker: $MONIKER"
      exit 1
  fi

  echo "Validator details:"
  echo "$VALIDATOR_DATA" | jq '.'
  ```
</Accordion>

### Critical Metrics

Monitor these validator-specific metrics:

```bash theme={"dark"}
# Check signing status
seid query slashing signing-info $(seid tendermint show-validator)

# Check current delegations
seid query staking delegations-to $(seid keys show -a $VALIDATOR_KEY)
```

## Backup Management

<Accordion title="Complete Automated Backup Script">
  ```bash theme={"dark"}
  #!/bin/bash
  BACKUP_DIR="/backup/sei"
  DATE=$(date +%Y%m%d)
  NODE_HOME="/root/.sei"

  # Create backup directory
  mkdir -p $BACKUP_DIR

  # Stop service
  systemctl stop seid

  # Backup configuration
  tar czf $BACKUP_DIR/sei-config-$DATE.tar.gz $NODE_HOME/config

  # Backup data directory
  tar czf $BACKUP_DIR/sei-data-$DATE.tar.gz $NODE_HOME/data

  # Backup key files
  tar czf $BACKUP_DIR/sei-keys-$DATE.tar.gz $NODE_HOME/keyring-file

  # Start service
  systemctl start seid

  # Remove backups older than 7 days
  find $BACKUP_DIR -type f -mtime +7 -name '*.tar.gz' -delete

  # Log backup completion
  echo "Backup completed successfully on $(date)" >> $BACKUP_DIR/backup.log
  ```
</Accordion>

## Host System Monitoring

### Resource Usage Tracking

Install and configure node\_exporter:

```bash theme={"dark"}
wget https://github.com/prometheus/node_exporter/releases/download/v1.5.0/node_exporter-1.5.0.linux-amd64.tar.gz
tar xvf node_exporter-1.5.0.linux-amd64.tar.gz
```

Add to Prometheus configuration:

```yaml theme={"dark"}
scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['localhost:9100']
```

## EVM RPC OpenTelemetry Metrics

The EVM RPC layer emits OpenTelemetry metrics through the process-wide `MeterProvider` (for example, a Prometheus exporter). These are emitted in parallel with the legacy `sei_*` metrics so you can migrate dashboards incrementally.

### Available EVM RPC Metrics

| Metric                                         | Type      | Description                                                                                                                                     |
| ---------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `evmrpc_request_latency_seconds`               | Histogram | EVM RPC request latency in seconds.                                                                                                             |
| `evmrpc_websocket_connects_total`              | Counter   | Number of new websocket connections.                                                                                                            |
| `evmrpc_redirected_requests_total`             | Counter   | Number of EVM RPC requests forwarded to another validator. Labeled by `endpoint` and `connection`.                                              |
| `evmrpc_historical_debug_trace_attempts_total` | Counter   | Number of `debug_trace*` requests targeting historical blocks beyond the configured max block lookback. Labeled by `endpoint` and `connection`. |

The `evmrpc_request_latency_seconds` histogram carries the following labels:

| Label          | Description                                                                                                                                                                                                                                 |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `endpoint`     | The RPC method being served (for example, `eth_getBalance`).                                                                                                                                                                                |
| `connection`   | The connection type serving the request (for example, `http` or `websocket`).                                                                                                                                                               |
| `success`      | Boolean indicating whether the request succeeded.                                                                                                                                                                                           |
| `error_class`  | A low-cardinality classification of the failure. An empty string denotes success. Possible values include `panic`, `execution_reverted`, `evm_not_supported`, `sei_legacy_disabled`, `association_missing`, `jsonrpc_error`, and `unknown`. |
| `jsonrpc_code` | A low-cardinality bucket for the JSON-RPC error code: `spec` (predefined range `-32700..-32600`), `server` (server-defined range `-32099..-32000`), or `other`. An empty string denotes no code (success or an untyped error).              |

### Migrating from Legacy EVM RPC Metrics

The following legacy `sei_*` metrics remain available today but are deprecated and scheduled for removal once dashboards migrate to the `evmrpc_*` OpenTelemetry metrics:

| Legacy metric                | Replacement                                                                                            |
| ---------------------------- | ------------------------------------------------------------------------------------------------------ |
| `sei_rpc_request_latency_ms` | `evmrpc_request_latency_seconds`                                                                       |
| `sei_websocket_connect`      | `evmrpc_websocket_connects_total`                                                                      |
| `sei_rpc_request_counter`    | `evmrpc_request_latency_seconds` (use the histogram count with the `success` and `error_class` labels) |

Update your Prometheus and Grafana dashboards to consume the `evmrpc_*` metrics before the legacy metrics are removed. Note that latency changed units from milliseconds (`sei_rpc_request_latency_ms`) to seconds (`evmrpc_request_latency_seconds`), so adjust any thresholds and panel formatting accordingly.

## FlatKV OpenTelemetry Metrics

The FlatKV state store emits OpenTelemetry metrics through the process-wide `MeterProvider` (for example, a Prometheus exporter). These metrics let node operators observe commit throughput, catchup progress, snapshotting, rollbacks, and snapshot imports.

### Available FlatKV Metrics

| Metric                                 | Type      | Description                                                 |
| -------------------------------------- | --------- | ----------------------------------------------------------- |
| `flatkv_open_latency`                  | Histogram | Time taken to open the FlatKV store (seconds).              |
| `flatkv_apply_changesets_latency`      | Histogram | Time taken to apply changesets to FlatKV (seconds).         |
| `flatkv_commit_latency`                | Histogram | Time taken to commit FlatKV changes (seconds).              |
| `flatkv_commit_batch_latency`          | Histogram | Time taken to commit a FlatKV data DB batch (seconds).      |
| `flatkv_batch_read_old_values_latency` | Histogram | Time taken to batch read old FlatKV values (seconds).       |
| `flatkv_num_kv_pairs`                  | Counter   | Number of key-value pairs applied to FlatKV.                |
| `flatkv_pending_writes`                | Gauge     | Current number of pending FlatKV writes.                    |
| `flatkv_current_version`               | Gauge     | Current committed FlatKV version.                           |
| `flatkv_catchup_latency`               | Histogram | Time taken to replay FlatKV WAL entries (seconds).          |
| `flatkv_catchup_replay_num_blocks`     | Counter   | Number of FlatKV WAL entries replayed during catchup.       |
| `flatkv_snapshot_write_latency`        | Histogram | Time taken to write a FlatKV snapshot (seconds).            |
| `flatkv_snapshot_prune_latency`        | Histogram | Time taken to prune FlatKV snapshots (seconds).             |
| `flatkv_snapshot_prune_attempts`       | Counter   | Total number of FlatKV snapshot prune attempts.             |
| `flatkv_current_snapshot_height`       | Gauge     | Current FlatKV snapshot height.                             |
| `flatkv_rollback_latency`              | Histogram | Time taken to rollback FlatKV state (seconds).              |
| `flatkv_import_latency`                | Histogram | Time taken to import FlatKV snapshot data (seconds).        |
| `flatkv_import_kv_pairs`               | Counter   | Number of key-value pairs imported into FlatKV.             |
| `flatkv_import_worker_flush_latency`   | Histogram | Time taken to flush a FlatKV import worker batch (seconds). |
| `flatkv_flush_latency`                 | Histogram | Time taken to flush a FlatKV data DB (seconds).             |

### Labels

FlatKV metrics carry the following labels where applicable:

| Label       | Description                                                                                                                                                                                                                                                                                                   |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `db`        | The data DB the measurement applies to (for example, `account`, `storage`, `code`, or `legacy`). Present on per-DB metrics such as `flatkv_commit_batch_latency`, `flatkv_flush_latency`, `flatkv_num_kv_pairs`, `flatkv_pending_writes`, `flatkv_import_kv_pairs`, and `flatkv_import_worker_flush_latency`. |
| `success`   | Boolean indicating whether the operation succeeded. Present on latency and attempt metrics that can fail.                                                                                                                                                                                                     |
| `read_only` | Boolean present on `flatkv_open_latency` indicating whether the store was opened read-only.                                                                                                                                                                                                                   |

### Enabling Pebble Internal Metrics

Pebble's internal (per-DB) metrics are governed by a single FlatKV-level knob: `enable-pebble-metrics` under `[state-commit.flatkv]` in `app.toml` (default `true`). The key is honored when present but is not part of the `app.toml` that `seid init` generates, so add it manually to change the default. Its value is propagated to every data DB (account, code, storage, legacy, and metadata) during initialization and overrides any per-DB `EnableMetrics` settings, so configure Pebble metrics through this knob rather than the individual per-DB settings.

## LittDB OpenTelemetry Metrics

LittDB now emits its metrics through the process-wide OpenTelemetry `MeterProvider` instead of a private Prometheus client. When `MetricsEnabled` is set, LittDB configures a Prometheus exporter on the global provider and serves `/metrics` on `MetricsPort` (default `9101`). The previous `MetricsNamespace` and `MetricsRegistry` config fields have been removed; all metric names now use a fixed `litt_` prefix.

### Available LittDB Metrics

| Metric                                      | Type      | Unit    | Description                                                                                                                                                                              |
| ------------------------------------------- | --------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `litt_table_size_bytes`                     | Gauge     | bytes   | The size of individual tables in the database.                                                                                                                                           |
| `litt_table_key_count`                      | Gauge     | count   | The number of keys in individual tables in the database.                                                                                                                                 |
| `litt_open_iterator_count`                  | Gauge     | count   | The number of currently-open iterators for individual tables in the database. A persistently nonzero value indicates a leaked iterator, which suspends garbage collection for the table. |
| `litt_bytes_read`                           | Counter   | bytes   | The number of bytes read from disk since startup.                                                                                                                                        |
| `litt_keys_read`                            | Counter   | count   | The number of keys read from disk since startup.                                                                                                                                         |
| `litt_cache_hits`                           | Counter   | count   | The number of cache hits since startup.                                                                                                                                                  |
| `litt_cache_misses`                         | Counter   | count   | The number of cache misses since startup.                                                                                                                                                |
| `litt_read_latency_seconds`                 | Histogram | seconds | Read latency of the database, including both cache hits and cache misses.                                                                                                                |
| `litt_cache_miss_latency_seconds`           | Histogram | seconds | Read latency measured only when a cache miss occurs.                                                                                                                                     |
| `litt_bytes_written`                        | Counter   | bytes   | The number of bytes written to disk since startup (values only, not metadata).                                                                                                           |
| `litt_keys_written`                         | Counter   | count   | The number of keys written to disk since startup.                                                                                                                                        |
| `litt_write_latency_seconds`                | Histogram | seconds | Write latency of the database.                                                                                                                                                           |
| `litt_flush_count`                          | Counter   | count   | The number of times a flush operation has been performed.                                                                                                                                |
| `litt_flush_latency_seconds`                | Histogram | seconds | Latency of a flush operation.                                                                                                                                                            |
| `litt_segment_flush_latency_seconds`        | Histogram | seconds | Segment flush latency; a subset of the time spent during a flush operation.                                                                                                              |
| `litt_keymap_flush_latency_seconds`         | Histogram | seconds | Keymap flush latency; a subset of the time spent during a flush operation.                                                                                                               |
| `litt_garbage_collection_latency_seconds`   | Histogram | seconds | Latency of garbage collection operations.                                                                                                                                                |
| `litt_chunk_cache_key_count`                | Gauge     | count   | The number of keys in the chunk cache.                                                                                                                                                   |
| `litt_chunk_cache_weight_bytes`             | Gauge     | bytes   | The weight of the chunk cache in bytes.                                                                                                                                                  |
| `litt_chunk_cache_keys_added`               | Counter   | count   | The number of keys added to the chunk cache.                                                                                                                                             |
| `litt_chunk_cache_weight_added_bytes`       | Counter   | bytes   | The weight of the entries added to the chunk cache.                                                                                                                                      |
| `litt_chunk_cache_eviction_latency_seconds` | Histogram | seconds | Eviction latency of the chunk cache.                                                                                                                                                     |

### Attributes

| Attribute | Description                                                                                                                                                                                                                 |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `table`   | The table the observation applies to. Present on per-table metrics such as `litt_bytes_read`, `litt_read_latency_seconds`, `litt_table_size_bytes`, and the flush/GC latency histograms.                                    |
| `cache`   | The cache instance the observation applies to (`chunk_read` or `chunk_write`). Present on the `litt_chunk_cache_*` metrics, which distinguish read and write caches by this attribute rather than by separate metric names. |

### Migrating from Legacy LittDB Metrics

Metric names, units, and shape changed with the OpenTelemetry migration, so existing Prometheus and Grafana dashboards must be updated:

* Latency metrics moved from millisecond summaries (for example `{namespace}_read_latency_ms`) to second histograms (`litt_read_latency_seconds`). Adjust thresholds and panel formatting from milliseconds to seconds accordingly.
* Counters and gauges gained a fixed `litt_` prefix and explicit units, for example `bytes_read` became `litt_bytes_read` and the cache weight gauge became `litt_chunk_cache_weight_bytes`.
* The per-cache series that were previously separate metric names (for example `chunk_read_cache_*` and `chunk_write_cache_*`) are now the shared `litt_chunk_cache_*` metrics distinguished by the `cache` attribute.
* The `MetricsNamespace` and `MetricsRegistry` config fields no longer exist. Metric names are fixed, and metrics are always backed by the global OTel provider; supply the scrape port via `MetricsPort`.

## Performance Testing

<Accordion title="Example Benchmark Script using `eth_getLogs`">
  ```js theme={"dark"}
  import { ethers } from 'ethers';

  // Configuration
  const EVM_RPC_URL = 'http://localhost:8545'; // EVM RPC endpoint to test
  const CONTRACT_ADDRESS = '0x0000000000000000000000000000000000001002'; // replace with very active contract for best results
  const INITIAL_BLOCK_RANGE = 50; // range of blocks to query using 'eth_getLogs'
  const RANGE_INCREMENT = 10; // additional blocks to query each consecutive round
  const MAX_TESTS = 50; // total number of rounds for testing

  // Store metrics for final analysis
  const metrics = [];

  function getResponseSize(logs) {
    return Buffer.byteLength(JSON.stringify(logs), 'utf8');
  }

  function formatBytes(bytes) {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
  }

  function padString(str, length) {
    return String(str).padEnd(length);
  }

  function analyzeResults(metrics) {
    console.log('\nPerformance Analysis');
    console.log('='.repeat(50));

    // Filter out queries with no logs for meaningful statistics
    const queriesWithLogs = metrics.filter((m) => m.logsCount > 0);
    const totalQueries = metrics.length;

    console.log(`\nGeneral Statistics:`);
    console.log(`Total Queries Run: ${totalQueries}`);
    console.log(`Queries with Logs: ${queriesWithLogs.length}`);
    console.log(`Empty Responses: ${totalQueries - queriesWithLogs.length}`);

    if (queriesWithLogs.length > 0) {
      const avgResponseTime = queriesWithLogs.reduce((acc, m) => acc + m.responseTime, 0) / queriesWithLogs.length;
      const avgLogsPerQuery = queriesWithLogs.reduce((acc, m) => acc + m.logsCount, 0) / queriesWithLogs.length;
      const maxLogs = Math.max(...queriesWithLogs.map((m) => m.logsCount));
      const maxLogsQuery = queriesWithLogs.find((m) => m.logsCount === maxLogs);

      console.log(`\nPerformance Metrics:`);
      console.log(`Average Response Time (with logs): ${avgResponseTime.toFixed(2)}ms`);
      console.log(`Average Logs per Query: ${avgLogsPerQuery.toFixed(2)}`);
      console.log(`Maximum Logs in Single Query: ${maxLogs}`);
      if (maxLogsQuery) {
        console.log(`- At Range Size: ${maxLogsQuery.rangeSize} blocks`);
        console.log(`- Response Time: ${maxLogsQuery.responseTime}ms`);
        console.log(`- Efficiency: ${maxLogsQuery.logsPerMs.toFixed(3)} logs/ms`);
      }

      // Identify optimal range size based on logs/ms
      const bestEfficiency = queriesWithLogs.reduce((best, m) => (m.logsPerMs > best.logsPerMs ? m : best));
      console.log(`\nOptimal Performance:`);
      console.log(`Best Efficiency: ${bestEfficiency.logsPerMs.toFixed(3)} logs/ms`);
      console.log(`- At Range Size: ${bestEfficiency.rangeSize} blocks`);
      console.log(`- Retrieved ${bestEfficiency.logsCount} logs in ${bestEfficiency.responseTime}ms`);
    }
  }

  async function testEthGetLogs() {
    const provider = new ethers.JsonRpcProvider(EVM_RPC_URL);

    try {
      const latestBlock = await provider.getBlockNumber();
      console.log(`Latest block: ${latestBlock} (0x${latestBlock.toString(16)})`);

      let currentToBlock = latestBlock;
      let currentRange = INITIAL_BLOCK_RANGE;
      let testCount = 0;

      // Column headers with fixed widths
      console.log('\nBlock Range         Time  Logs    Size     B/ms   Logs/ms  KB/Log  Range');
      console.log('='.repeat(80));

      while (testCount < MAX_TESTS && currentToBlock > 0) {
        const fromBlock = Math.max(0, currentToBlock - currentRange);

        try {
          const startTime = Date.now();
          const filter = {
            fromBlock: fromBlock,
            toBlock: currentToBlock,
            address: CONTRACT_ADDRESS
          };

          const logs = await provider.getLogs(filter);

          const endTime = Date.now();
          const responseTime = endTime - startTime;
          const logsCount = logs.length;
          const responseSize = getResponseSize(logs);

          // Calculate metrics
          const bytesPerMs = (responseSize / responseTime).toFixed(1);
          const logsPerMs = (logsCount / responseTime).toFixed(3);
          const kbPerLog = logsCount > 0 ? (responseSize / 1024 / logsCount).toFixed(2) : 'N/A';

          // Store metrics for analysis
          metrics.push({
            rangeSize: currentRange,
            responseTime,
            logsCount,
            responseSize,
            bytesPerMs: parseFloat(bytesPerMs),
            logsPerMs: parseFloat(logsPerMs),
            kbPerLog: kbPerLog !== 'N/A' ? parseFloat(kbPerLog) : 0
          });

          // Format block range
          const rangeDisplay = `${fromBlock.toString(16)}-${currentToBlock.toString(16)}`;

          // Log with fixed column widths
          console.log(padString(rangeDisplay, 17) + padString(responseTime, 6) + padString(logsCount, 8) + padString(formatBytes(responseSize), 9) + padString(bytesPerMs, 8) + padString(logsPerMs, 9) + padString(kbPerLog, 8) + currentRange);

          if (logsCount === 10000) {
            console.log(`\nWarning: Hit 10000 log limit at range ${currentRange}`);
          }

          currentToBlock = fromBlock - 1;
          currentRange += RANGE_INCREMENT;
          testCount++;
        } catch (error) {
          console.log(`Error at range ${currentRange}: ${error.message}`);
          currentRange = Math.max(INITIAL_BLOCK_RANGE, currentRange - RANGE_INCREMENT);
          currentToBlock = fromBlock - 1;
          testCount++;
        }

        await new Promise((resolve) => setTimeout(resolve, 1000));
      }

      // Perform final analysis
      analyzeResults(metrics);
    } catch (error) {
      console.error('Failed to initialize or get latest block:', error);
      process.exit(1);
    }
  }

  // Run the test
  testEthGetLogs();
  ```
</Accordion>

For specific customizations or additional metrics, consult the Sei
technical communities in [Telegram](https://t.me/+ZN-NcvOWStQwMzk0) or
[Discord](https://discord.gg/sei).
