> ## Documentation Index
> Fetch the complete documentation index at: https://docs.risingwave.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Specific bottlenecks

> Identify and resolve specific resource bottlenecks in RisingWave, including CPU, memory, storage, and more.

This topic provides detailed guidance on diagnosing and addressing specific resource bottlenecks that can cause high latency and slow stream processing in RisingWave. If the [General troubleshooting approach](/performance/performance-troubleshoot-ov) and the [High latency](/performance/troubleshoot-high-latency) troubleshooting guide have pointed you towards a potential resource limitation, this section will help you confirm the issue and find solutions.

## CPU bottleneck

If you suspect that insufficient CPU resources are causing high latency, examine the following metrics and consider the recommended actions.

In your Grafana dashboard (dev), navigate to **Cluster Node** > **Node CPU panel**, and locate the **cpu usage (avg per core) - compute** metric:

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/cpu-usage.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=15d9ad0330e72a672513e9f4b4e70b0f" alt="CPU Usage" width="787" height="297" data-path="images/performance/cpu-usage.png" />

*Figure 1: CPU usage panel in Grafana.*

**Indicators:**

* CPU usage (avg per core) consistently exceeds 80%. See [Resource utilization](/performance/metrics#resource-utilization).

**Actions:**

* Consider scaling up (adding more cores to a Streaming Node) or scaling out (adding more Streaming Nodes to the cluster). See [Resource allocation](/performance/best-practices#resource-allocation).

**Caveats:**

* Low CPU usage *doesn't* necessarily mean you can scale down. If the bottleneck is caused by slow state reads/updates due to insufficient memory, shrinking Compute Nodes might worsen the situation.
* High memory usage is expected in RisingWave, as it utilizes available memory for caching. For details, see [Why is the memory usage so high?](/faq/faq-using-risingwave#why-the-memory-usage-is-so-high).

## State access bottleneck (read)

Slow state access can significantly impact performance. This section helps you diagnose issues related to reading state data from the executor cache, storage, and storage cache. If you suspect issues with state access, start by checking [Cache performance](/performance/metrics#cache-performance).

### Executor cache

In your Grafana dashboard (dev), navigate to **Streaming Actors** > **Executor Cache Memory Usage** panel.

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/executor-cache-memory-usage.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=933ae0835e82b9792670c5dfd033baa2" alt="Executor Cache Memory Usage" width="773" height="298" data-path="images/performance/executor-cache-memory-usage.png" />

*Figure 2: Executor cache memory usage in Grafana.*

And navigate to the **Streaming Actors** > **Executor Cache Miss Ratio** panel:

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/executor-cache-miss-ratio.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=a5976dee0a44738c1b37adc6aee4414a" alt="Executor Cache Miss Ratio" width="792" height="297" data-path="images/performance/executor-cache-miss-ratio.png" />

*Figure 3: Executor cache miss ratio in Grafana.*

**Indicators:**

* Executor memory usage is significantly smaller than expected for the workload.
* High executor cache miss ratio.

**Actions:**

* Increase Streaming Node memory by scaling up or scaling out. See [Resource allocation](/performance/best-practices#resource-allocation).

### Storage read

You can use the Grafana dashboard (dev) > **Actor/Table Id Info** > **State Table Info** to check the table name, table type, and the associated materialized view and fragment ID of a state table. You can infer the executor type by looking at the `table_name`.

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/state-table-info.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=c22fb0bc7bc8d0a20c9c8fa192a7f8a2" alt="State Table Info" width="788" height="302" data-path="images/performance/state-table-info.png" />

*Figure 4: State table info in Grafana.*

You can use the "Table" filter at the top of the Grafana page to choose metrics specific to `table_id(s)` shown in the storage metrics.

Example:

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/grafana-table-filter.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=08de1d47ed0223210f735c803dee85f3" alt="Grafana Table Filter" width="1457" height="189" data-path="images/performance/grafana-table-filter.png" />

*Figure 5: Using the "Table" filter in Grafana.*

When there is an executor cache miss, state reads are handled by the storage layer. There are two types of storage reads:

* **`Get`:** Used for point lookups (e.g., by `HashAgg` executors).
* **`Iter`:** Used for range/prefix scans (e.g., by `HashJoin` executors).

#### Get operations

Navigate to Grafana dashboard (dev) > **Hummock (Read)** > **Read Duration (Get)**

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/read-duration-get.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=49725942f1fddc6ec6666b00689f0c8b" alt="Read Duration Get" width="783" height="287" data-path="images/performance/read-duration-get.png" />

*Figure 6: Read duration (Get) in Grafana.*

The "Read Duration - (Get)" panel shows a histogram of `Get` durations for each state table.

**Indicators:**

* `avg` / `p99` duration consistently 10-100ms or higher.

**Actions:**

* Investigate potential storage cache issues (see below).

#### Iter operations

Navigate to Grafana dashboard (dev) > **Hummock (Read)** > **Read Duration (Iter)**

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/read-duration-iter.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=146e82a639baedefb17c36f89da402e9" alt="Read Duration Iter" width="783" height="294" data-path="images/performance/read-duration-iter.png" />

*Figure 7: Read duration (Iter) in Grafana.*

The "Read Duration - (Iter)" panel shows a histogram of `Iter` durations, divided into:

* `create_iter_time`: Time to initialize the storage iterator (fetching metadata, pruning files, initial seek).
* `pure_scan_time`: Time spent scanning data within the iterator.

**Indicators:**

* `p99` duration consistently 10-100ms or higher.

**Actions:**

* Check for excessive tombstones or stale keys (see below).
* Investigate potential storage cache issues (see below).

#### Tombstones and stale keys

Navigate to Grafana dashboard (dev) > **Hummock (Read)** > **Iter Keys flow**

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/iter-keys-flow.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=761d5a41616acc5265fd2d43b6d4b340" alt="Iter Keys Flow" width="773" height="295" data-path="images/performance/iter-keys-flow.png" />

*Figure 8: Iter keys flow in Grafana.*

The "Iter keys flow" panel tracks the operations per second (OPS) of different key types:

* `processed`: Visible keys processed.
* `skip_delete`: Tombstone keys encountered (marked for deletion).
* `skip_multi_version`: Stale keys encountered (older versions of data).

**Indicators:**

* High `skip_delete` and `skip_multi_version` values indicate that the compaction process is lagging.

**Actions:**

* Investigate potential [Compaction bottleneck](#compaction-bottleneck).

### Storage cache

RisingWave's storage engine (Hummock) uses two types of cache:

* **Block cache (data cache):** Caches blocks of data from stored files (SSTs). Each block is typically 64KB.
* **Meta cache:** Caches metadata about stored files (SSTs).

#### Block cache

Navigate to Grafana dashboard (dev) > **Hummock (Read)** > **Cache Size**.

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/read-cache-size.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=6cff18ea3d8fccdd41dd5e0e3fe83def" alt="Cache Size" width="784" height="296" data-path="images/performance/read-cache-size.png" />

*Figure 9: Cache size in Grafana.*

Navigate to Grafana dashboard (dev) > **Hummock (Read)** > **Cache Miss Ratio**

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/cache-miss-ratio.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=9589f776b0bfdbc53f941c05fc3b6be8" alt="Cache Miss Ratio" width="784" height="296" data-path="images/performance/cache-miss-ratio.png" />

*Figure 10: Cache miss ratio in Grafana.*

**Indicators:**

* High block cache miss ratio. This is influenced by both executor state access locality (better locality = lower miss ratio) and block cache capacity (smaller capacity relative to the working set = higher miss ratio).

**Actions:**

* Scale up the Streaming Node or tune memory configurations. See [Resource allocation](/performance/best-practices#resource-allocation).

**Caveats:**

* A high miss *ratio* alone doesn't always indicate a problem. Consider the *absolute number* of misses. A low miss ratio with a very high number of total operations can still result in significant latency.

#### Meta cache

Navigate to Grafana dashboard (dev) > **Hummock (Read)** > **Cache Ops**.

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/cache-ops.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=a351f6ca56ea3479ab3f5dd9c595e624" alt="Cache Ops" width="782" height="368" data-path="images/performance/cache-ops.png" />

*Figure 11: Cache operations in Grafana.*

* `meta_miss`: Should ideally be close to 0%.
* `data_miss`: Represents misses that require access to the remote object store.

**Indicators:**

* `meta_miss` is non-zero.
* `data_miss` is high.

**Actions:**

* Scale up the Streaming Node or tune memory configurations.
* Investigate potential [Object store issues](#object-store-issues).

## State update bottleneck (write)

If state updates are slow, executors may be blocked while waiting for space in the storage write buffer (also known as the shared buffer).

**Indicators:**

There are two ways to check whether the state update is backpressured by a full shared buffer:

1. **Search for `blocked at requiring memory` in CN logs**. If it shows up, some state table writes are waiting for the shared buffer quota to be released.
2. **Check the “uploading memory - compute” metric** (Grafana dashboard (dev) > **Hummock (Write)** > **Uploader Memory Size**). The shared buffer capacity is by default configured to be 4GB at max. If you see this time series consistently at or near the maximum, the shared buffer is likely full.

Navigate to ***Grafana dashboard (dev) > Hummock (Write) > Uploader Memory Size***

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/uploader-memory-size.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=bf178d651fc073635651f6584834011a" alt="Uploader Memory Size" width="789" height="304" data-path="images/performance/uploader-memory-size.png" />

*Figure 12: Uploader memory size in Grafana.*

There can be multiple causes that can lead to the state update bottleneck.

### Slow object store writes

The shared buffer can only be released after in-memory state updates are flushed to the persistent remote object store.

Navigate to ***Grafana dashboard (dev) > Streaming > Barrier sync latency***

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/barrier-sync-latency.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=b4331cc46c3a88b544410bd954fec92f" alt="Barrier Sync Latency" width="786" height="296" data-path="images/performance/barrier-sync-latency.png" />

*Figure 13: Barrier sync latency in Grafana.*

**Indicators:**

* Barrier sync latency takes up most of the barrier latency.

**Actions:**

* Investigate potential [Object store issues](#object-store-issues).

**Caveat:**

* High barrier sync latency doesn't *always* mean slow object store writes. An overwhelmed storage event handler can also cause this.

### Overwhelmed storage event handler

Storage uses an event loop to propagate storage events. If events pile up, state uploads can be delayed.

Navigate to ***Grafana dashboard (dev) > Hummock (Write) > Event handler pending event number***

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/pending-event-number.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=19ed89d8722169ca39e29275def62098" alt="Event Handler Pending Event Number" width="778" height="287" data-path="images/performance/pending-event-number.png" />

*Figure 14: Event handler pending event number in Grafana.*

**Indicators:**

* The event number remains consistently high. This often indicates too many actors/state tables on a single Streaming Node.

**Actions:**

* Check the per-compute-node actor count: Grafana dashboard (dev) > **Actor/Table Id Info** > **Actor Count (Group By Compute Node)**
* Add more Compute Nodes and rebalance actors.

## Compaction bottleneck

Compaction merges and reorganizes data in storage, improving query performance and reclaiming space. Compaction bottlenecks can manifest in two main ways:

### Write stall

**Indicators:**

* Rows returned by this SQL query:

  ```sql theme={null}
  => SELECT id,
            compaction_config->>'level0StopWriteThresholdSubLevelNumber' as write_stop_threshold,
  					active_write_limit
     FROM rw_hummock_compaction_group_configs
     WHERE active_write_limit is not null;
   id | write_stop_threshold |                         active_write_limit
  ----+----------------------+---------------------------------------------------------------------
    3 | 300                  | {"reason": "too many L0 sub levels: 301 > 300", "tableIds": [1001]}
  (1 row)
  ```

* Data points shown in Grafana dashboard (dev) > **Hummock Manager** > **Write Stop Compaction Groups**.
  <img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/write-stop-compaction-groups.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=cae0607ee8519e3471b17115372b567d" alt="Write Stop Compaction Groups" width="2000" height="772" data-path="images/performance/write-stop-compaction-groups.png" />
  *Figure 15: Write stop compaction groups in Grafana.*

* Compactor CPU is fully utilized: Grafana dashboard (dev) > **Cluster Node** > **Node CPU panel**, find the "cpu usage (avg per core) - compactor"
  <img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/cpu-usage.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=15d9ad0330e72a672513e9f4b4e70b0f" alt="Compactor CPU" width="787" height="297" data-path="images/performance/cpu-usage.png" />
  *Figure 16: Compactor CPU usage in Grafana.*

* Await Tree is stuck during the flush (visible in the Await Tree Dump).

**Actions:**

* Scale up/out compactors. A recommended ratio is CN cores : compactor cores = 2 : 1.
* Investigate potential [Object store issues](#object-store-issues).
* If scaling doesn't resolve the issue, collect compactor logs, snapshots of the "Object Store" and "Compaction" panels in the Grafana dev dashboard, and the results of these SQL queries for further investigation:
  ```sql theme={null}
  SELECT compaction_group_id,
         level_id,
         level_type,
         sub_level_id,
         count(*)                       AS total_file_count,
         round(Sum(file_size) / 1024.0) AS total_file_size_kb
  FROM   rw_catalog.rw_hummock_sstables
  GROUP  BY compaction_group_id,
            level_type,
            level_id,
            sub_level_id
  ORDER  BY compaction_group_id,
            level_id,
            sub_level_id DESC;

  SELECT * FROM rw_hummock_compaction_group_configs;
  ```

**Caveats:**

* Compactors are primarily CPU-bound, so you can allocate less memory if needed (e.g., 4C 4GB is acceptable).

### Too many tombstones or stale keys

Navigate to ***Grafana dashboard (dev) > Hummock Manager > Epoch***

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/epoch.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=84cd96a4281f61b96b3017de19770f5e" alt="Epoch" width="779" height="302" data-path="images/performance/epoch.png" />

*Figure 17: Epoch information in Grafana.*

Data between `safe_epoch` and `max_committed_epoch` is readable in a multi-version concurrency control (MVCC) manner. Compaction cannot reclaim data written above `min_pinned_epoch`.

**Indicators:**

* A large gap between `safe_epoch` / `min_pinned_epoch` and `max_committed_epoch`.

**Actions:**

* Check for long-running batch queries: `SHOW PROCESSLIST;`
* Trigger a manual recovery: `RECOVER;`
* Restart all serving nodes.

## UDF bottleneck

Slow User-Defined Function (UDF) calls can significantly impact performance, as UDF invocation is in the critical path of streaming computation.

Navigate to ***Grafana dashboard (dev) > User Defined Function section***

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/udf-section.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=0504468a7df1d73f379d9f0f537a9feb" alt="UDF Section" width="1282" height="946" data-path="images/performance/udf-section.png" />

*Figure 18: User-defined function metrics in Grafana.*

**Indicators:**

* Consistently high UDF latency.

**Actions:**

* Check for network calls or I/O within the UDF.
* If using a UDF server, verify good network connectivity between RisingWave and the server.

## Object store issues

Navigate to ***Grafana dashboard (dev) > Object Store > Operation Rate/Duration/Failure Rate/Retry Rate***

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/operation-metrics.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=8fc2e927cf96275968113c0056e7d6ba" alt="Object Store Metrics" width="1582" height="604" data-path="images/performance/operation-metrics.png" />

*Figure 19: Object store metrics in Grafana.*

Potential causes of object store slowness include:

1. **High Operation Duration:** Check logs for errors/warnings.
2. **High Operation Rate:** With S3, >3000 OPS may cause duration spikes. Consider scaling up Compute Nodes to reduce cache misses.
3. **Persistent Operation Failure Rate:** Indicates misconfiguration or network/object store unavailability. Check logs.
4. **Persistent Operation Retry Rate:** Indicates misconfiguration or network/object store unavailability. Check logs. If retries are due to timeouts, consider tuning retry configurations.

## Sink issues

Navigate to ***Grafana dashboard (dev) > User Streaming Errors > Sink Errors By Type***

<img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/sink-errors.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=a10a7f2193b56461a9a22ecc31ae495e" alt="Sink Errors" width="786" height="298" data-path="images/performance/sink-errors.png" />

*Figure 20: Sink errors in Grafana.*

You should ideally see no errors here. If errors are present, search for "sink" and "Error" in the node logs.

If other indicators (e.g., the Await Tree Dump) suggest a sink bottleneck, consider enabling sink decoupling to isolate temporary sink slowness. See [Sink decoupling](/delivery/overview#sink-decoupling).

**Caveats:**

* Sink decoupling isolates the sink but doesn't improve its throughput. If the log store lag increases after enabling decoupling, investigate the sink itself:

  Navigate to ***Grafana dashboard (dev) > Sink Metrics > Log Store Lag***

  <img src="https://mintcdn.com/risingwavelabs/32PTodGr5zqa37oO/images/performance/log-store-lag.png?fit=max&auto=format&n=32PTodGr5zqa37oO&q=85&s=0b14f092555486cade7228189271b9f8" alt="Log Store Lag" width="786" height="300" data-path="images/performance/log-store-lag.png" />

  *Figure 21: Log store lag in Grafana.*
