Travis (YaaaDingus)
09/22/2026, 4:33 PMRocky
09/22/2026, 4:35 PMMemTracker to track memory usage by adding up every allocation made by its various components (queries, metadata, cache, etc.).
* The Issue: MemTracker is an "accounting" system at the application level. It can diverge significantly from the Resident Set Size (RSS) or Working Set reported by K8s if there are discrepancies in how allocations/deallocations are tracked.
* Common Symptom: You may see MemTracker reporting 80–90% usage (triggering "high memory" logs or query cancellations), while K8s metrics (RSS) show the pod is only using 40% of its physical limit. This is often due to internal trackers "leaking" accounting units even if the actual memory was freed.
2. TCMalloc "Reserved" Memory
StarRocks uses TCMalloc as its memory allocator. When a query finishes, TCMalloc doesn't always return memory to the OS immediately.
* Page Heap Freelist: TCMalloc may hold memory in a "freelist" to reuse for the next query.
* StarRocks' View: StarRocks may count this "reserved" memory as used in its internal metrics, or TCMalloc may report it as "in use by application" even though the OS hasn't reclaimed the pages yet.
* K8s View: K8s pod metrics (specifically container_memory_working_set_bytes) might exclude these inactive pages, leading to a much lower reported usage.
3. Container Memory Limit Detection
By default, the mem_limit parameter in be.conf (which CNs also use) is set to 90%.
* If StarRocks fails to correctly detect the K8s pod limit via cgroups, it may calculate that 90% against the host node's total RAM instead of the pod's limit.
* Result: If the host has 512GB but the pod is limited to 64GB, StarRocks might think it has 460GB available and won't trigger internal GC or spill-to-disk until it's far beyond the pod's 64GB limit, causing OOM kills—or conversely, if it miscalculates the limit downward, it might report "high memory" prematurely.
How to Troubleshoot
To see what StarRocks actually thinks is happening, check these endpoints directly on the CN:
1. View detailed component breakdown:
http://<CN_IP>:8040/mem_tracker
Look for which label (e.g., query_pool, load, page_cache) has high Current Consumption.
2. Check TCMalloc stats:
http://<CN_IP>:8040/memz
Compare Bytes in use by application with Bytes in page heap freelist. If the freelist is huge, TCMalloc is holding memory.
3. Verify the limit StarRocks sees:
Check the log (<http://be.INFO|be.INFO>) or the /metrics endpoint for starrocks_be_process_mem_limit_bytes. Ensure this matches your K8s pod limit.
Recommended Actions
* Set explicit `mem_limit`: Instead of a percentage, set mem_limit in be.conf (or via the Helm chart/Operator) to a specific byte value slightly lower than your K8s pod limit (e.g., if pod limit is 64Gi, set mem_limit = 58G).
* Enable TCMalloc Aggressive Release (if applicable): If you see a massive page heap freelist in /memz, you can tune TCMalloc decay times, though this is usually managed automatically in newer StarRocks versions.
* Upgrade: If you are on an older version, there were known bugs (e.g., Issue #67607) where MemTracker was inaccurate in container environments; these are improved in versions 3.2.x and 3.3.x+.Travis (YaaaDingus)
09/22/2026, 4:38 PMTravis (YaaaDingus)
09/22/2026, 4:39 PMRocky
09/22/2026, 4:39 PMcontainer_memory_working_set_bytes shows only 40%.
* Status in 4.0.8: While 4.0.8 included optimizations for releasing Spill Operator memory earlier, some tracking inaccuracies in container environments persisted until later patches in the 4.1.x line.
2. MemTracker vs. RSS (Working Set)
* K8s Metrics: Usually show RSS (Resident Set Size) or Working Set, which is the physical RAM currently mapped to the process.
* StarRocks MemTracker: Includes "virtual" accounting. For example, if TCMalloc (the memory allocator) holds onto memory in its "page heap" for reuse, StarRocks may still count this as "used" by a specific tracker, whereas the OS might treat it as reclaimable/inactive.
3. Cgroup Limit Detection
In K8s, if mem_limit is set as a percentage (default 90%), StarRocks 4.0.x attempts to detect the container limit. If it fails to read the cgroup limit correctly, it might calculate that 90% based on the Host’s physical RAM instead of the Pod’s limit.
* Verification: Check your CN/BE logs (<http://be.INFO|be.INFO>) for the string process memory limit. If it shows a value much larger or smaller than your K8s pod limit, the detection is failing.
Recommended Troubleshooting Steps
1. Identify the "Leaking" Tracker:
Access the node's debug page: http://<CN_IP>:8040/mem_tracker.
Look for which label has the highest Current Consumption. If query_pool or load is high but no queries/loads are running, it confirms a tracking accounting error.
2. Check TCMalloc Status:
Access http://<CN_IP>:8040/memz.
Check the Total physical memory usage. If this is low (matching your K8s metrics) but MemTracker is high, the issue is purely internal accounting.
3. Hard-code the Memory Limit:
To prevent StarRocks from miscalculating or being overly aggressive based on percentages, set a hard byte limit in `be.conf`:
conf
# Example for a 64GiB Pod
mem_limit = 58G
This forces the internal thresholds to align with your allocated K8s resources.
4. Upgrade to 4.1.x:
If you are experiencing the specific "MemTracker over-counting" bug mentioned in 4.0.x issues, consider moving to the 4.1.x branch (e.g., 4.1.3), which includes significantly more robust memory tracking and cgroup v2 support for containerized environments.Travis (YaaaDingus)
09/22/2026, 5:01 PMRocky
09/22/2026, 5:01 PMMemTracker when memory is released to the allocator. This is particularly common on the Compute Node (CN) with metadata-heavy workloads or frequent tablet updates.
* Jemalloc Retained Memory: StarRocks uses jemalloc (or tcmalloc). The allocator may hold onto "retained" virtual memory that hasn't been physically mapped (RSS). If StarRocks' trackers are tracking these virtual reservations instead of physical allocations, the discrepancy grows.
* Data Cache (Starlet) Metadata: On CN nodes, the metadata for the local data cache (starlet_cache) can sometimes be over-counted or fail to release its tracker units even after the cache is purged.
2. Immediate Diagnostic Steps
To identify the culprit, you must check the internal state of the specific "high memory" node:
1. Identify the Leaking Component:
Access the node's debug interface: http://<NODE_IP>:8040/mem_tracker
* Look for the Label with the highest Current Consumption.
* Common culprits: query_pool, table_meta, or storage_page_cache.
* If the sum of all labels is much higher than your K8s RSS, it confirms an internal accounting bug.
2. Verify Allocator vs. OS:
Access http://<NODE_IP>:8040/memz
* Check Total physical memory usage. If this matches the K8s pod metrics (low), then the memory is physically free.
* Check Retained memory. If this is very high (e.g., 40GB+), jemalloc is holding virtual address space that the tracker is misinterpreting as "used."
3. Recommended Actions
* Tune Allocator Decay: You can force the allocator to return memory to the OS more aggressively by adjusting these be.conf parameters (requires restart):
conf
# Speed up memory reclamation
dirty_decay_ms = 1000
muzzy_decay_ms = 1000
* Hard-code `mem_limit`: Instead of using the default 90%, set a hard byte limit in be.conf that matches your K8s limit (e.g., mem_limit = 58G for a 64Gi pod). This sometimes stabilizes the tracker's threshold calculations in containers.
* Check for Data Skew: Since only one node is affected, run SHOW TABLETS FROM <table_name> to ensure data isn't skewed. A single "hot" tablet or a large metadata object on that node can keep a tracker pinned high.
* Upgrade Note: If you are on 4.1.4, you are on a very recent version. If the tracker for table_meta or query_pool remains high with no active tasks, it is likely a remaining edge case of the MemTracker bug. Capturing the output of /mem_tracker and /memz and reporting it to the community is recommended.
Temporary Workaround: A restart of the affected node will reset the internal counters, but the discrepancy may slowly return if the underlying accounting leak persists.
References
• knowledge/trouble_shooting/fe_memory_problems.md
• faq/fe_mem_faq.md
• using_starrocks/caching/block_cache.md
• administration/management/resource_management/Memory_management.mdTravis (YaaaDingus)
09/22/2026, 5:22 PMRocky
09/22/2026, 5:22 PM~6.9GB used while Kubernetes reports `<3GiB`—is a confirmed issue in the 4.x branch related to MemTracker accounting drift and Allocator retention in containerized environments.
Even on version 4.1.4, the internal "safety brake" in StarRocks (the MemTracker) can become out of sync with the actual physical memory (RSS) tracked by Kubernetes cgroups.
Why the discrepancy exists
1. Virtual vs. Physical Memory: StarRocks uses an internal counter (MemTracker) to track every memory allocation. If the memory allocator (usually jemalloc or tcmalloc) allocates memory from the OS but hasn't physically mapped it to RAM yet, or if it holds onto "retained" memory for future use, StarRocks' tracker may count it as "Used," while Kubernetes (RSS) sees it as free.
2. Accounting Leaks (Issue #67607): There are known cases in the 4.x line where certain code paths (particularly in shared-data mode/CN nodes) fail to decrement the internal counter when a task finishes. This causes the "Used" metric in the error message to climb indefinitely until it hits the limit, even if no physical RAM is being consumed.
3. TCMalloc/Jemalloc Decay: The default settings for memory reclamation in StarRocks are often too "lazy" for containers. The allocator might wait 5+ seconds to return memory to the OS, but the internal StarRocks trackers might treat that un-reclaimed memory as a hard allocation.
Immediate Troubleshooting
To confirm where the "phantom" memory is located, run these two commands against the affected node (cn-1):
1. Check the breakdown:
curl http://<CN_IP>:8040/mem_tracker
Look for a specific Label that is unusually high (e.g., query_pool, table_meta, or storage_page_cache). If the sum of these is ~6.9GB but your queries are minimal, it's an accounting leak.
2. Check Allocator Stats:
curl http://<CN_IP>:8040/memz
Look for "Retained memory" or "Bytes in page heap freelist." If this value is large (several GBs), the allocator is holding memory that the OS thinks is free, but StarRocks' safety limits are treating as "Used."
Recommended Fixes
Apply these settings to your cn.conf (or via the Helm chart config section) to force more accurate behavior:
* Aggressive Memory Release:
Force the allocator to return memory to the OS faster. This reduces the gap between StarRocks "Used" and K8s "RSS."
conf
# Add to cn.conf
muzzy_decay_ms = 1000
dirty_decay_ms = 1000
* Hard-code `mem_limit`:
StarRocks sometimes miscalculates its 90% limit when running in K8s. Instead of a percentage, set a hard byte limit that is roughly 10% less than your K8s Pod limit:
conf
# If your Pod limit is 8Gi, set this to ~7Gi
mem_limit = 7G
* Disable MemPool (Last Resort):
If the accounting drift is severe and related to small allocations, you can disable the internal pool to force more direct tracking:
conf
disable_mem_pools = true
Note on "Machine Metrics": Your host metrics show 364Mi free but 15Gi available. This is normal Linux behavior—the OS is using that 15Gi for Page Cache (disk caching), which it will instantly release if a process needs it. StarRocks is likely ignoring this, but the internal tracker error you're seeing is independent of the host's page cache.
References
• administration/management/resource_management/Memory_management.md
• knowledge/trouble_shooting/fe_memory_problems.md
• faq/fe_mem_faq.mdTravis (YaaaDingus)
09/22/2026, 5:26 PMRocky
09/22/2026, 5:26 PMMemTracker. If certain code paths fail to "decrement" the counter when memory is freed, the internal "Used" value climbs until it hits the limit, triggering a "False OOM" that cancels queries.
1. Confirming the Accounting Drift
Access the following debug endpoints on the affected node (cn-1):
* Check the Breakdown: curl http://<CN_IP>:8040/mem_tracker
* Look for the process tracker. If process says 6.9GB but the sum of its children (like query_pool, load, table_meta) is significantly less, the "leak" is in the accounting logic itself or in an untracked component.
* Check the Allocator: curl http://<CN_IP>:8040/memz
* Look for "Actual memory used (physical)". If this value is close to 3GB (matching your Pod metrics), it proves the allocator has returned the memory to the OS, but StarRocks' MemTracker failed to notice.
2. Why the Limit is 6.9GB
The limit 6957847018 (~6.48 GiB) suggests your Pod has a memory limit of approximately 7.2 GiB (StarRocks defaults to a hard limit of 90% of the detected container RAM). StarRocks is correctly seeing its container ceiling, but its "imaginary" usage has hit that ceiling.
3. Immediate Mitigations (4.1.4)
Since you are already on 4.1.4, you should apply the following configurations to cn.conf (or your Helm values.yaml) to force more accurate tracking and reclamation:
1. Force Aggressive Memory Release:
StarRocks 4.x uses jemalloc by default. These settings force it to return memory to the OS faster, which helps keep the internal trackers in sync with physical reality:
conf
muzzy_decay_ms = 1000
dirty_decay_ms = 1000
2. Adjust Tracking Precision:
Ensure the jemalloc tracker daemon is active (it should be by default in 4.x):
conf
enable_jemalloc_memory_tracker = true
3. Set a Hard Byte Limit:
To prevent StarRocks from being overly aggressive based on its 90% calculation, hardcode the limit to a specific value slightly below your Pod limit:
conf
# If Pod limit is 8Gi, set BE to 7Gi
mem_limit = 7G
4. Restart the Node:
Because this is an accounting error, the "Used" value will not go down until the process is restarted. Once restarted, the counters reset to zero.
4. Known Bugs in 4.1.4
There is a specific issue (#67607) in the 4.x branch where metadata tracking in shared-data mode (CN nodes) can drift significantly over time. Version 4.1.5 and later include specific fixes for "inaccurate memory accounting" in joins and tablet metadata reclamation. If the drift returns quickly after a restart, an upgrade to the latest patch in the 4.1.x line is recommended.
Summary of your Metrics:
* StarRocks "Used": 6.9GB (Internal counter - Incorrect/Buggy)
* Pod Metrics: < 3GB (Physical RAM - Correct)
* Machine Available: 15GB (Host Page Cache - Irrelevant to Pod limit)
References
• administration/management/resource_management/Memory_management.md
• faq/resource_isolation_faq.md
• administration/management/BE_configuration.md
• administration/management/resource_management/resource_group.mdTravis (YaaaDingus)
09/22/2026, 5:30 PMRocky
09/22/2026, 5:30 PMhttp://<CN_IP>:8040/mem_tracker
The page displays a table with a Label column and a Parent Label column. To see the children of "process":
* Look for all rows where the Parent Label is exactly process.
* Common top-level children include:
* `query_pool`: Memory used by active/recent queries.
* `load`: Memory used by data ingestion (MemTables).
* `table_meta`: Metadata for tablets, schemas, and rowsets.
* `storage_page_cache`: The BE's internal data page cache.
* `compaction`: Memory used by background merging of data.
* `column_pool`: Memory used for caching column-level data.
2. Drilling Down via URL Parameters
If the table is too large, you can filter for specific sub-pools using query parameters:
* To see the breakdown of query memory:
http://<CN_IP>:8040/mem_tracker?type=query_pool&upper_level=3
* To see metadata details:
http://<CN_IP>:8040/mem_tracker?type=table_meta
3. How to interpret the "Discrepancy"
When you see process = 6GB but Pod metrics = 3GB, there are two possibilities you should look for in the children:
* Scenario A: The "Lying Child"
One of the children (e.g., query_pool) also reports high usage (e.g., 4GB) even though no queries are running. This means a specific component failed to "check in" its memory release.
_ _Fix:* Identify which label is high and check if it matches your workload.
* Scenario B: The "Ghost Leak" (The most likely case for you)
If you sum up all the children (query_pool + table_meta + load + etc.) and they only add up to ~3GB, but the process tracker still says 6GB, the accounting error is at the root level.
* The process tracker increments and decrements as memory is requested from the allocator. In versions 4.0.x and 4.1.x, some code paths "forget" to decrement the root tracker when memory is freed.
* Because the root tracker hits the 6GB limit, it triggers the "Memory exceed limit" error, even though the children (and the OS) know the memory is actually free.
Quick Command to Sum Children
If you have curl and awk access, you can quickly see the sum of the children from the metrics endpoint to compare with the process total:
bash
curl -s http://<CN_IP>:8040/metrics | grep "starrocks_be_mem_pool_mem_usage_bytes"
If the values here don't add up to the process_mem_bytes (also in /metrics), it confirms the internal accounting drift.
References
• administration/management/resource_management/Memory_management.md
• administration/management/monitoring/metrics.md
• best_practices/query_tuning/query_profile_operator_metrics.mdTravis (YaaaDingus)
09/22/2026, 5:31 PMRocky
09/22/2026, 5:32 PMquery_pool or load), or it failed to "decrement" the counter when that memory was freed.
2. Gap 2: Root (6.9GB) vs. OS/Pod Metrics (<3GB): There is a ~4GB gap between what StarRocks thinks it is using and what it is actually consuming in RAM.
StarRocks uses an internal safety mechanism (the MemTracker) to prevent OOM kills by the OS. However, in your version, this safety mechanism has "drifted." It thinks the process is at the limit (6.9GB) and is proactively killing queries to "save" the node, even though the OS shows the node is perfectly healthy with 4GB+ of actual headroom.
Why this happens in Shared-Data (CN) Nodes
In shared-data mode, CN nodes frequently handle small, short-lived metadata objects for the object storage cache.
* Untracked Allocations: Some memory allocated by the jemalloc allocator (like internal metadata or fragmentation) is not always captured by the child trackers but is caught by the root process tracker.
* Metadata Leak: In some 4.x/3.x versions, the metadata cache for the Starlet (storage) layer could drift.
* Version Bug: There are known accounting bugs where specific code paths (often in joins or object storage metadata) fail to release the counter on the root tracker.
How to Fix It
1. Immediate Workaround (Clear the counters)
The internal counters do not "self-correct" once they drift this far. You must restart the affected CN node. This will reset the process tracker to match the actual RAM usage.
2. Tune Allocator Behavior
Add these to your cn.conf (or Helm chart configuration) to force the memory allocator to be more honest and return memory to the OS/Tracker faster:
conf
# Force jemalloc to release "dirty" memory to the OS more aggressively
muzzy_decay_ms = 1000
dirty_decay_ms = 1000
# Ensure jemalloc internal metadata is tracked (v3.2.12+)
enable_jemalloc_memory_tracker = true
3. Set a Static Memory Limit
If you are running in Kubernetes, StarRocks' calculation of "90% of available RAM" can sometimes conflict with how K8s reports cgroup limits. Hardcode the limit to a value about 10-15% below your Pod's RAM limit:
conf
# If Pod limit is 8Gi, set this
mem_limit = 7G
4. Verify the "Ghost" Memory
To see exactly what the root tracker is seeing that the children are not, check the memz endpoint:
curl <http://starrocks-share-data-mode-cn-1>...:8040/memz
Look for "Bytes in page heap freelist" and "MALLOC: ... Bytes in use by application".
* If Bytes in use by application is ~3GB (matching Pod metrics) but the StarRocks error says 6.9GB, it is a confirmed accounting bug in the StarRocks MemTracker logic.
Recommendation: If this drift recurs within 24–48 hours after a restart, you likely need to upgrade to the latest patch release (e.g., if on 3.2.x, go to 3.2.13+; if on 4.x, ensure you are on the latest 4.1.x patch), as several "memory accounting drift" fixes were merged recently for CN nodes.
References
• administration/management/BE_configuration.md
• administration/management/resource_management/Memory_management.md
• administration/management/monitoring/metrics.mdTravis (YaaaDingus)
09/22/2026, 5:34 PMactive: 6492336128
mapped: 7174430720
retained: 5239136256
base: 138799168
internal: 15235072
metadata_thp: 71
tcache_bytes: 98863400
tcache_stashed_bytes: 0
resident: 7084969984
abandoned_vm: 0
extent_avail: 86818Rocky
09/22/2026, 5:35 PMmemz data you provided clarifies the situation: Your node is physically using 6.6GB of RAM, and the StarRocks "process" tracker is accurately reporting this.
The data from the allocator (jemalloc) explains the breakdown:
* active: 6.49 GB: This is the memory StarRocks has actually requested and is actively using. This matches your "process" tracker (6GB+).
* resident: 6.60 GB: This is the actual physical RAM (RSS) being held by the node.
* retained: 4.88 GB: This is virtual memory space jemalloc has mapped but isn't necessarily using yet.
1. The Discrepancy Analysis
You have two different "gaps" occurring:
* Gap A: Children vs. Process (~1.5GB Gap): You mentioned the children sum to < 5GB, but active is 6.5GB. This means 1.5GB of memory is "Untracked." It was allocated by StarRocks code but didn't check into a child MemTracker (like query_pool or load).
* Gap B: Jemalloc vs. Pod Metrics: You see < 3GB in Pod metrics, but memz shows 6.6GB resident. This usually means your Pod metrics are looking at a specific container or a delayed metric, whereas the allocator (memz) has a direct view of the process heap. *Trust the memz values*—they are the reason your queries are being killed.
2. Common "Untracked" Sources in CN Nodes
Since you are in shared-data mode, the 1.5GB of untracked memory is likely one of the following:
* Object Storage Metadata/Cache: Metadata for S3/OSS/HDFS files (Starlet/Starlight layers) is sometimes under-reported in child trackers in older 4.x/3.x versions.
* Zonemap/Index Memory: Memory for segment zonemaps (segment_zonemap_mem_bytes).
* Jemalloc Metadata: Internal overhead of the allocator (though your internal says only 15MB, so this is not the main culprit).
* Thread Stacks: If there is a high concurrency of threads.
3. Action Plan
Since you have hit the 6GB Limit, StarRocks is performing as designed by stopping new allocations. To resolve this:
1. Increase the `mem_limit`: If your Kubernetes Pod has more than 6.6GB available (e.g., if the Pod limit is 8GB or 12GB), you should manually set mem_limit in cn.conf to a higher value. StarRocks defaults to 90% of what it detects, which may be conservative in your K8s setup.
conf
# Example: set to 7 Gigabytes
mem_limit = 7G
2. Force Memory Release: Add these to cn.conf to force jemalloc to return memory to the OS more aggressively, which can help lower the resident memory:
conf
muzzy_decay_ms = 1000
dirty_decay_ms = 1000
3. Upgrade to 4.1.5+: There is a known issue (#67607) in the 4.1.x line where memory accounting in container environments is inaccurate. Upgrading to the latest patch will include fixes that better track the "untracked" 1.5GB you are seeing.
4. Check for "Zonemap" usage: Run this command on the CN node to see if a specific untracked metric is high:
curl -s localhost:8040/metrics | grep _mem_bytes
Summary: Your node is not experiencing a "phantom" leak; it is actually using 6.5GB. Because you set (or defaulted) the limit to 6GB, it is now in self-protection mode. Increase the limit or restart the node to clear the untracked 1.5GB.
References
• administration/management/BE_configuration.md
• administration/management/resource_management/Memory_management.md
• faq/shared_data_faq.md
• administration/management/FE_configuration.md
• faq/resource_isolation_faq.md
• faq/fe_mem_faq.md
• administration/management/monitoring/metrics.mdTravis (YaaaDingus)
09/22/2026, 5:47 PMRocky
09/22/2026, 5:48 PMquery_pool).
1. The Root Cause in v4.1.5 (Shared-Data)
In shared-data mode, the 1.5GB–2GB "gap" you see is typically allocated to the Lake Metadata Cache and Starlet Object Buffers. These are "Active" allocations (as seen in your memz data) but are often not assigned a specific label in the mem_tracker UI.
In v4.1.5, two specific areas were addressed but may still require configuration:
* Lake Column Updates (#77275): If you use Primary Key tables, the process of applying "delete vectors" to segments during a query consumes significant memory. While 4.1.5 improves this by "streaming" the segments, it still requires a buffer in the process heap.
* Data Cache Metadata: The datacache (if enabled) stores small metadata items inline in memory.
2. Diagnosis: Identify the "Untracked" Memory
Check the following metrics to see if they account for the missing ~1.5GB:
bash
curl -s localhost:8040/metrics | grep -E "lake_metadata_cache|starlet|datacache_metadata"
* starrocks_be_lake_metadata_cache_usage_bytes: This is a major source of untracked memory. It caches segment and tablet info from S3/Object storage.
* starrocks_be_datacache_metadata_usage_bytes: Memory used to index your local disk cache.
3. How to fix it in 4.1.5
Since your memz shows active: 6.49 GB (actual usage) but your limit is likely near 6GB, you must either increase the limit or cap the internal caches.
Option A: Increase the Hard Limit (Recommended)
If your Pod has the headroom, manually raise the mem_limit. StarRocks’ automatic detection (90%) sometimes miscalculates in K8s, leading it to "self-throttle" while the Pod is still healthy.
conf
# Set this in cn.conf (Example: if Pod is 8G, set to 7G)
mem_limit = 7G
Option B: Cap the Lake Metadata Cache
If the metrics show lake_metadata_cache is high, you can limit it (this is a hidden/internal configuration in some versions, but you can try adjusting the following in cn.conf):
conf
# Limit the metadata cache for lake segments
lake_metadata_cache_limit = 512M
# Aggressively release memory back to the OS
muzzy_decay_ms = 1000
dirty_decay_ms = 1000
Option C: Reduce Data Cache Overhead
If you have a large datacache, the metadata required to track those millions of small files can take up ~1GB of RAM.
* Check if datacache_mem_size is set too high.
* If you don't need a memory-level data cache (only disk), ensure datacache_mem_size = 0.
Summary for v4.1.5
The "Process" tracker is correct (as verified by your memz active bytes), but the "Child" trackers are incomplete. The memory is being used by the storage layer (Lake/Starlet).
1. Restart the node to clear the current accumulation.
2. Raise mem_limit to 7G or 8G to give the storage layer the workspace it clearly needs.
3. Check Primary Key usage: If this happens during heavy updates to PK tables, it is likely the delete-vector application process.
References
• administration/management/BE_configuration.md
• administration/management/resource_management/Memory_management.md
• faq/shared_data_faq.md
• administration/management/monitoring/metrics.md
References
• administration/management/BE_configuration.mdTravis (YaaaDingus)
09/22/2026, 6:56 PMRocky
09/22/2026, 6:56 PMmemz output you provided confirms that StarRocks is physically using 6.49GB (active) and the OS-level resident memory is 7.08GB. This means the StarRocks tracker is actually accurate—the 6.9GB it reports is "real" memory used by the process heap.
1. Where is the "Untracked" 1.5GB?
Since your previous grep didn't catch the byte-count metrics, please run this broader command to find the specific component using the "missing" memory:
bash
curl -s localhost:8040/metrics | grep -E "_mem_used_bytes|_meta_used_bytes|_usage_bytes|tablet_metadata_mem_bytes"
Specifically, look for:
* block_cache_meta_used_bytes: Memory used for Data Cache indexing.
* tablet_metadata_mem_bytes: Metadata for the Lake tablets.
* starrocks_be_lake_metadata_cache_usage_bytes: Cache for segment/tablet info from S3.
2. Discrepancy with Pod Metrics
You mentioned your Pod metrics show < 3GB, but memz shows resident: 7.08 GB.
* StarRocks is definitely using 7GB. The "Memory Limit Exceeded" error is correct.
* The Pod metrics you are seeing might be delayed, looking at a different container, or misinterpreting cgroup memory (some tools show "Cache" vs "RSS" differently). *Trust the memz and StarRocks error logs*—the allocator (jemalloc) is holding 7GB of RAM.
3. Immediate Fixes for v4.1.5
If the process is hitting the limit at 6.9GB, it suggests your node is configured with a ~7.5GB limit (90% of 8GB). To stop the query failures, you have three options:
A. Increase the Memory Limit (Easiest)
If your Kubernetes Pod has more RAM (e.g., 10GB+), manually set the mem_limit to a higher fixed value in cn.conf. This gives the "untracked" storage layer more room to breathe.
conf
# Example for a 12GB Pod
mem_limit = 10G
B. Cap the Lake Metadata Cache
In shared-data mode, the metadata cache for remote files can grow. You can limit it by adding this to `cn.conf`:
conf
# Reduce the percentage of mem_limit used for metadata (default is often 30%)
metadata_cache_memory_limit_percent = 10
C. Forcejemalloc to Release Memory
Your memz shows retained: 5.2GB and resident: 7.08GB. This indicates jemalloc is being "lazy" about returning memory to the OS. Add these to cn.conf and restart:
conf
muzzy_decay_ms = 1000
dirty_decay_ms = 1000
Recommendation: Restart the CN node to clear the current 6.9GB heap. If it climbs back to 6.9GB quickly, check the metrics in Step 1. If block_cache_meta_used_bytes is the culprit, you may need to reduce your datacache disk size or increase the Pod RAM.
References
• using_starrocks/caching/block_cache.md
• administration/management/monitoring/metrics.md
• data_source/data_cache_observe.mdTravis (YaaaDingus)
09/22/2026, 6:57 PMRocky
09/22/2026, 6:58 PMMemTracker tree.
* Lake Metadata Cache: Caching tablet metadata files from S3.
* Jemalloc Metadata/Fragmentation: Your memz shows active: 6.5GB and resident: 7.1GB. The 0.6 GB difference is allocator overhead and fragmentation.
2. The contradiction with Pod Metrics
You mentioned your Pod metrics show < 3 GB, but memz reports resident: 7.08 GB.
* resident is the physical RAM (RSS) the OS has assigned to the process.
* If memz says 7 GB, the process is physically holding 7 GB.
* Why the Pod discrepancy? Many Kubernetes monitoring tools (like standard Prometheus/Grafana dashboards) show "Memory Usage" as RSS - Cache. In shared-data mode, StarRocks' use of mmap or specific allocator behaviors can sometimes cause container runtimes to misclassify memory. *Trust the memz output*—the process is hitting its internal 6.9 GB limit, which is why queries are failing.
3. Recommended Fixes for v4.1.5
Since the query is failing because it hits the limit, you need to either give the "Untracked" memory more room or cap the internal caches.
A. Increase mem_limit (Primary Solution)
If your Kubernetes Pod has more than 8 GB of RAM available (e.g., a 12 GB or 16 GB limit), the StarRocks mem_limit is likely set too low by default. Manually increase it in `cn.conf`:
conf
# If your Pod has 12GB, set this to 10G
mem_limit = 10G
B. Aggressive Memory Release
Your memz shows retained: 5.2 GB. This is virtual memory jemalloc is holding onto. While not physical RAM, it can interfere with how StarRocks calculates its "Process" tracker. Add these to cn.conf to force jemalloc to be less "greedy":
conf
muzzy_decay_ms = 1000
dirty_decay_ms = 1000
C. Control Lake Metadata
Since you are in shared-data mode, the metadata for tablets can grow. You can try to cap it (though it is often untracked in child trackers, it counts toward the total):
conf
# Limit the lake metadata cache (adjust as needed)
lake_metadata_cache_limit = 512M
D. Check for Primary Key Heavy Usage
In 4.1.5, if you are querying tables with many updates/deletes (Primary Key model), the Delete Vector application can consume significant memory that is often reported at the "Process" level but lacks a detailed child tracker. If this is the case, consider increasing the Pod's memory allocation.
Next Step: I recommend increasing the mem_limit to 8G or 10G (if the Pod allows) and restarting the node. This usually resolves the "Memory Limit Exceeded" errors caused by the ~2GB of untracked storage-layer overhead.
References
• administration/management/BE_configuration.md
• administration/management/resource_management/Memory_management.md
• faq/shared_data_faq.md
References
• faq/shared_data_faq.md
• administration/management/monitoring/metrics-shared-data.mdTravis (YaaaDingus)
09/22/2026, 7:09 PMRocky
09/22/2026, 7:09 PMSELECT ... LIMIT 20 query taking a long time despite low Pod-reported memory is a classic symptom of Metadata Bloat or Small File Fragmentation in the shared-data storage layer.
Here is why this is happening and how to fix it:
1. Why LIMIT 20 is slow
Even if you only want 20 rows, StarRocks must first identify which "Segments" (files) on S3 contain the data. If your table has insufficient compaction, the CN node has to download and parse thousands of small metadata files from S3 just to find those 20 rows.
Diagnose this via the Query Profile:
Run the query with profiling enabled:
sql
SET enable_profile = true;
-- Run your slow query here --
SELECT get_query_profile(last_query_id());
Look for these specific indicators in the profile:
* SegmentsReadCount: If this is in the hundreds or thousands for a simple limit query, your table is fragmented.
* IOTimeRemote / CompressedBytesReadRemote: High values here mean the node is spending all its time waiting on S3/Object Storage.
* TabletMetadataMemBytes: Check if this is high (visible in the /metrics endpoint as well).
2. The Memory Discrepancy (Process vs. Pod)
Your memz shows 7.08GB Resident, but your Pod metrics show < 3GB.
* StarRocks is right; the Pod metrics are wrong. Many Kubernetes tools exclude "Cache" or "Mapped" memory. StarRocks uses mmap and jemalloc for the storage layer (Starlet/Lake), which often gets misclassified by cgroup-based monitoring but is physically occupied.
* The "Process" tracker in StarRocks is the only one that sees these storage-layer allocations. The "Children" trackers (like query_pool) only track the execution layer.
3. Immediate Solutions for v4.1.5
A. Force Compaction
If SegmentsReadCount is high, your background compaction is likely lagging. In shared-data mode, you can check the compaction score:
sql
-- Check if any partition has a score > 100
SELECT * FROM information_schema.lake_compaction_score WHERE max_score > 100;
If scores are high, you can manually trigger compaction (if supported for your table type) or increase the background compaction threads in `cn.conf`:
conf
compact_threads_num = 8
lake_compaction_max_tasks = 16
B. Fix the "Untracked" Memory Bloat
In v4.1.5, the "Process" memory is often inflated by jemalloc holding onto "retained" memory. Force it to be more aggressive in releasing RAM back to the system. Add this to cn.conf and restart the CN:
conf
# Force faster memory release
muzzy_decay_ms = 1000
dirty_decay_ms = 1000
# Cap the metadata cache which is often the cause of the "Process" gap
lake_metadata_cache_limit = 512M
C. Manual Memory Limit
Because StarRocks sometimes misdetects container limits (especially in K8s), it may think it has 90% of the Host RAM rather than the Pod RAM, or vice-versa. Explicitly set a hard limit in `cn.conf`:
conf
# Set this to ~80-90% of your actual Pod RAM Request/Limit
mem_limit = 6G
Summary Recommendation
1. Restart the CN node to clear the 7GB resident memory.
2. Check the Compaction Score. If it's high, the "slow query" is caused by S3 metadata overhead, not the query execution itself.
3. Use the 4.1.5 "Streaming" fix: Ensure lake_enable_streaming_metadata_read = true (this should be default in 4.1.5) to prevent the metadata of every segment from being loaded into memory at once.
References
• loading/loading_introduction/troubleshooting_loading.md
• faq/Sql_faq.md
• best_practices/query_tuning/query_profile_text_based_analysis.mdTravis (YaaaDingus)
09/22/2026, 7:10 PMRocky
09/22/2026, 7:10 PMinformation_schema.partitions_meta.
1. Check Compaction Scores
Run this to see which tables/partitions have too many unmerged files (fragmentation):
sql
SELECT
DB_NAME,
TABLE_NAME,
PARTITION_NAME,
AVG_CS,
MAX_CS,
ROW_COUNT
FROM information_schema.partitions_meta
WHERE MAX_CS > 100
ORDER BY MAX_CS DESC;
* MAX_CS > 100: The partition is unhealthy. Queries will be slow because the CN must open too many small files/metadata blocks.
* MAX_CS > 500: Queries will likely time out or hit memory limits just trying to "list" the data files.
2. Check Ongoing Compaction Tasks
If the scores are high, check if the system is actually working on merging them:
sql
-- See summary of tasks
SHOW PROC '/compactions';
-- See detailed tablet-level progress
SELECT * FROM information_schema.be_cloud_native_compactions
WHERE STATUS != 'OK' OR PROGRESS < 100;
3. Why LIMIT 20 is slow and using 7GB RAM
In StarRocks shared-data mode:
1. Metadata Overhead: When you run SELECT ... LIMIT 20, the CN node must fetch the metadata for all segments in that table from S3 to determine where the data lives.
2. The Memory Gap: If you have 1,000s of small uncompacted files, that metadata is huge. This memory is allocated in the storage layer (Starlet), which is why it shows up in the "Process" tracker (7GB) but not in the "Query" child trackers.
3. The "Forever" wait: The CN is likely stuck in a loop downloading and parsing these metadata "footers" from S3.
Recommended Action
If MAX_CS is high (e.g., > 200), your background compaction is not keeping up with your ingestion rate.
1. Increase Compaction Resources in `cn.conf`:
conf
# Allow more concurrent compaction tasks
lake_compaction_max_tasks = 16
# Increase threads for compaction work
compact_threads_num = 8
2. Increase the CN Memory Limit: If your Pod has the head-room, set mem_limit = 10G (or higher) to allow the metadata cache to accommodate the fragmentation until compaction catches up.
3. Check Ingestion: If you are doing many small INSERT or ROUTINE LOAD commits, try to batch them into larger transactions (e.g., every 30-60 seconds instead of every 5 seconds).
References
• knowledge/admin_and_operation/shared_data_compaction.md
• administration/management/compaction.md
• administration/management/BE_configuration.md
References
• knowledge/admin_and_operation/shared_data_compaction.mdTravis (YaaaDingus)
09/22/2026, 7:21 PMRocky
09/22/2026, 7:22 PMmemz showed 5.2 GB of retained memory. This is memory that jemalloc has marked as free but hasn't returned to the OS. StarRocks counts this toward its process limit, which can block queries.
Run this command on the CN node to force an immediate release:
bash
# Replace <cn_ip> and <cn_http_port> (default 8040)
curl -X POST http://<cn_ip>:<cn_http_port>/api/release_memory
Note: This is a "best effort" release. If it doesn't drop the Resident memory significantly, the memory is physically tied to objects in the metadata cache.
2. Evict the "Untracked" Metadata Cache
The ~2GB "untracked" memory gap you see is likely the Lake Metadata Cache (caching file footers from S3). If ingestion is stopped, you can safely clear this to reset the memory state:
sql
-- Scale the metadata cache limit down to 0 to force eviction, then back up.
-- Check your BE_ID from 'SHOW BACKENDS' or use 'be_configs' globally.
UPDATE be_configs SET VALUE = "1M" WHERE NAME = "lake_metadata_cache_limit";
-- Wait 10 seconds --
UPDATE be_configs SET VALUE = "2G" WHERE NAME = "lake_metadata_cache_limit";
3. Why the Query "Takes Forever" (The Fragmentation Debt)
Stopping ingestion stops new fragments from being created, but it doesn't fix the ones that are already there. If SELECT ... LIMIT 20 is still slow:
* The Problem: The CN is still trying to open and parse the metadata of thousands of small files (Segments) stored on S3.
* Verify: Run the query and check the profile for SegmentsReadCount. If this number is high (e.g., > 500), the query is slow because of S3 metadata overhead.
* The Fix: You actually need compaction to run to merge these files. If you stopped it, the "debt" remains. Re-enable it but with restricted resources:
conf
# in cn.conf
lake_compaction_max_tasks = 4
compact_threads_num = 4
4. Critical v4.1.x Setting
Ensure that Streaming Metadata Read is enabled. This prevents the CN from loading the entire metadata of a large table into memory before starting the query:
sql
-- Check this setting
ADMIN SHOW FRONTEND CONFIG LIKE 'lake_enable_streaming_metadata_read';
-- If false, set it to true
ADMIN SET FRONTEND CONFIG ("lake_enable_streaming_metadata_read" = "true");
Summary of Next Steps:
1. Release jemalloc memory via the /api/release_memory HTTP call.
2. Clear the Data Cache using the UPDATE be_configs method mentioned above.
3. Check SegmentsReadCount in the Query Profile. If it's massive, you must let compaction finish its work to make the table "healthy" again. Stopping it only preserves the broken state.
References
• administration/management/BE_configuration.md
• data_source/data_cache_troubleshooting.md
• best_practices/query_tuning/query_profile_text_based_analysis.md
References
• data_source/data_cache_troubleshooting.md
• administration/management/BE_configuration.md
• best_practices/query_tuning/query_profile_text_based_analysis.md
References
• faq/shared_data_faq.mdRocky
09/22/2026, 7:22 PMTravis (YaaaDingus)
09/22/2026, 7:24 PMRocky
09/22/2026, 7:25 PMpartitions_meta.
A SELECT ... LIMIT 20 query taking a long time while the CN node shows high "Resident" memory (7GB) but low "Query" memory (<3GB) typically means the node is overwhelmed by S3/Object Storage Metadata. Each small file (segment) on S3 has a footer that must be loaded and cached to even begin a "simple" query.
1. Correct Diagnosis (v4.1.5)
Run this to see the actual fragmentation (Compaction Score) for your table:
sql
SELECT
DB_NAME,
TABLE_NAME,
PARTITION_NAME,
MAX_CS, -- Max Compaction Score
AVG_CS, -- Average Compaction Score
ROW_COUNT
FROM information_schema.partitions_meta
WHERE TABLE_NAME = 'your_table_name'
ORDER BY MAX_CS DESC;
* If MAX_CS > 100: You have too many small files. The CN is spending all its time downloading and parsing metadata footers from S3, which is why the "Process" memory is high but "Query" memory is low—this metadata caching happens in the storage layer (Starlet), not the query execution layer.
2. Verified Memory & Metadata Configs
In v4.1.x, you can limit the metadata cache specifically to prevent it from consuming all CN RAM. This is a BE/CN dynamic config:
sql
-- Check current limit (often defaults to a percentage of RAM)
SELECT * FROM information_schema.be_configs WHERE name = 'lake_metadata_cache_limit';
-- Manually cap it to 2GB to force eviction and free up Resident RAM
UPDATE information_schema.be_configs
SET value = '2147483648'
WHERE name = 'lake_metadata_cache_limit';
3. Fixing the "Forever" Query
Since stopping ingestion didn't help, the table is already in a "Small File Trap." To fix this in v4.1.5:
1. Enable File Bundling (if not already): This v4.0+ feature bundles small metadata and data files to reduce S3 API calls.
sql
ALTER TABLE your_table_name SET ("file_bundling" = "true");
2. Force Compaction: You need to actually run compaction to merge the existing small files. If it was stuck, check the status:
sql
-- Check active compaction tasks
SELECT * FROM information_schema.be_cloud_native_compactions WHERE STATUS != 'OK';
3. Adjust Compaction Concurrency (FE Config):
sql
-- Allow the FE to schedule more tasks if the score is high
ADMIN SET FRONTEND CONFIG ("lake_compaction_max_tasks" = "16");
4. Immediate Memory Release
To force the jemalloc allocator to return the "Resident" memory to the OS without a restart:
bash
curl -X POST http://<cn_ip>:8040/api/release_memory
Why it's not a hallucination: The discrepancy between Pod metrics and memz is real—K8s often misses memory mapped via mmap or held by jemalloc as "retained." Your CN is likely "healthy" from a Pod perspective but "starved" from a StarRocks internal perspective because the metadata cache has filled its internal mem_limit.
References
• administration/management/BE_configuration.md
• data_source/catalog/deltalake_catalog.md
• data_source/feature-support-data-lake-analytics.md
• data_source/catalog/iceberg/iceberg_catalog.mdTravis (YaaaDingus)
09/22/2026, 7:25 PMTravis (YaaaDingus)
09/22/2026, 7:25 PMRocky
09/22/2026, 7:26 PMsql
SELECT
BE_ID,
TXN_ID,
TABLET_ID,
START_TIME,
PROGRESS,
STATUS,
PROFILE
FROM information_schema.be_cloud_native_compactions
WHERE FINISH_TIME IS NULL
ORDER BY START_TIME ASC;
What to look for in the PROFILE column:
* read_remote_mb is high: The CN is downloading massive amounts of data from S3 because the data isn't in the local cache. This is slow and memory-intensive.
* read_remote_sec is high: S3/Object storage latency is the bottleneck.
* in_queue_sec is high: The CN is overloaded and tasks are waiting for a thread.
2. Check if FE is stuck on "Publish"
If the tasks show 100% progress but never disappear, the FE might be struggling to "Publish" the new version.
1. Run SHOW PROC '/compactions';.
2. If CommitTime is filled but FinishTime is NULL, the task is waiting for the FE to finalize the metadata. Check your Leader FE fe.log for any "publish version" errors.
3. Kill the "Zombie" or Heavy Tasks
If specific compactions have been running for hours and blocking your queries, cancel them to free up the CN:
sql
-- Use the TXN_ID from the previous SELECT query
CANCEL COMPACTION WHERE TXN_ID = 12345;
4. Tune the Compaction Performance
If compactions are slow but necessary, adjust these settings to make them more efficient:
* Increase IO Buffer: Increase the buffer used for reading from S3 during compaction (default 1MB).
sql
-- Dynamic BE/CN config
UPDATE information_schema.be_configs
SET value = "4194304" -- 4MB
WHERE name = "lake_compaction_stream_buffer_size_bytes";
* Enable File Bundling (v4.0+): This is critical for shared-data performance. It reduces the number of small metadata files on S3.
sql
ALTER TABLE your_table_name SET ("file_bundling" = "true");
5. Why LIMIT 20 is still slow
Even if you stop ingestion, the long-running compactions are likely:
1. Pinning Metadata: They keep large amounts of tablet metadata in the CN's RAM.
2. S3 Throughput: They may be saturating the S3 connection pool of the CN node, leaving no "slots" for your SELECT query to fetch data.
Recommendation:
1. Cancel all active compactions using CANCEL COMPACTION for the next 10 minutes.
2. Run your LIMIT 20 query. If it is fast now, you know the resource contention was the cause.
3. Re-enable compaction with lower concurrency so it doesn't overwhelm the CN again:
sql
ADMIN SET FRONTEND CONFIG ("lake_compaction_max_tasks" = "4");
References
• administration/management/compaction.md
• knowledge/admin_and_operation/shared_data_compaction.md
• sql-reference/information_schema/be_cloud_native_compactions.md
• administration/management/BE_configuration.md
References
• knowledge/admin_and_operation/shared_data_compaction.md
• administration/management/compaction.md
• faq/shared_data_faq.mdTravis (YaaaDingus)
09/22/2026, 7:28 PMRocky
09/22/2026, 7:29 PMmem_limit). When a compaction task tries to read and decompress data pages from S3 to merge them, it allocates memory. If the total memory used by the CN (including metadata cache, query execution, and other compaction threads) exceeds the limit, the process kills the task to prevent a full Pod OOM crash.
The limit you see (8697308774 bytes) is approximately 8.1 GB, which matches the Resident memory usage you observed.
To resolve this in v4.1.5, you need to reduce the "weight" of each compaction task so they fit within your 8GB RAM:
1. Reduce Merged Segments per Task (Most Effective)
The default setting allows merging up to 500–1000 files in one go, which is too much for an 8GB CN node. Reducing this significantly lowers the memory required for the "read and decompress" phase.
sql
-- Apply to the CN node (dynamic)
UPDATE information_schema.be_configs
SET value = "100"
WHERE name = "max_cumulative_compaction_num_singleton_deltas";
2. Lower Compaction Concurrency
If multiple compactions run at once, they each compete for that 8.1 GB. Lower the thread count to 2 to give each task more "breathing room":
sql
-- Apply to the CN node (dynamic)
UPDATE information_schema.be_configs
SET value = "2"
WHERE name = "compact_threads";
3. Adjust Per-Worker Memory Cap
StarRocks has a specific tracker for compaction. If individual tasks are too "fat," you can tighten their internal limit so they fail earlier or more gracefully before hitting the BE limit:
sql
-- This ensures a single thread doesn't hog more than 1.5GB
-- (Note: some versions require a restart for this config; check be_configs 'is_mutable')
UPDATE information_schema.be_configs
SET value = "1610612736"
WHERE name = "compaction_memory_limit_per_worker";
4. Verify CN mem_limit
Check how mem_limit is calculated. On a CN node with 8GB-10GB of RAM, you should ensure mem_limit is explicitly set to about 90% of the Pod's limit to leave room for the OS/Jemalloc overhead.
_ Check it via: SELECT _ FROM information_schema.be_configs WHERE name = 'mem_limit';
* If it is 0 or too high, set it in `cn.conf`: mem_limit = 80% (or a literal value like 7G).
Why this fixes the "Long Running" and "Forever" Query issues:
1. Failing Compaction = Fragmented Metadata: Because your compactions are OOMing, they never finish. This leaves your table with thousands of small files.
2. Metadata Overhead: Every time you run SELECT ... LIMIT 20, the CN has to load the metadata for all those files.
3. The Fix: By reducing max_cumulative_compaction_num_singleton_deltas to 100, the compactions will become "smaller" and faster. They will successfully complete, merge your small files into big ones, and your SELECT query will finally have less metadata to process, making it fast again.
Recommendation: Apply the max_cumulative_compaction_num_singleton_deltas = 100 and compact_threads = 2 settings immediately. This should allow the "long running" tasks to finish successfully instead of crashing.
References
• administration/management/BE_configuration.md
• administration/management/compaction.md
• knowledge/admin_and_operation/shared_data_compaction.md
• faq/Sql_faq.md
References
• administration/management/compaction.md
• administration/management/FE_configuration.md
• knowledge/admin_and_operation/shared_data_compaction.mdRocky
09/22/2026, 7:29 PMTravis (YaaaDingus)
09/22/2026, 7:29 PMRocky
09/22/2026, 7:29 PMUsed: 8.69GB, Limit: 8.1GB, StarRocks is proactively failing the task before the OS or Kubernetes can step in to kill the Pod.
1. The "90% Default" Rule
By default, StarRocks sets its internal mem_limit to 90% of the memory it detects.
* If your Pod has a 10GB limit, StarRocks recognizes ~9.6GB and sets its internal limit to ~8.6GB.
* The error message Limit: 8697308774 (~8.1 GB) indicates that StarRocks has calculated its safe operating ceiling at that level.
* Because StarRocks stops itself at 8.1GB, the Pod never reaches its 10GB K8s limit. This is a safety feature to prevent a full process crash (OOM Kill), which is much harder to recover from than a failed query or compaction task.
2. Tracker vs. RSS (Resident Set Size)
Kubernetes metrics usually show RSS (actual physical pages mapped). StarRocks' internal MemTracker is more "aggressive" and counts:
* Allocations before they happen: When a compaction thread asks for a 512MB buffer, the tracker adds 512MB to its "Used" count immediately. The OS won't show this in RSS until the thread actually writes data to those pages.
* Jemalloc Metadata: Since v3.2.12, StarRocks includes jemalloc internal metadata in its accounting. This metadata can be significant (hundreds of MBs) and is often "invisible" to standard process monitoring tools but is tracked internally.
* Dirty Pages: jemalloc often holds onto memory it has "freed" but hasn't returned to the OS yet (dirty pages). StarRocks tracks this as "Used" because it's still reserved for the process, even if the OS doesn't count it as active RSS.
3. Why you don't see it in the Pod stats
If you are looking at a Prometheus/Grafana dashboard for "Pod Memory Usage," you are likely seeing a 30-second or 1-minute average.
* Memory spikes during "read and decompress" phases of compaction are micro-spikes.
* StarRocks' internal tracker checks the limit in real-time (sub-millisecond).
* If a spike hits the internal 8.1GB limit for even a fraction of a second, the task is killed. The monitoring system, sampling every 30 seconds, will never "see" that peak; it just sees a flat line at 7GB.
How to verify this
You can see exactly what StarRocks thinks is using the memory by looking at the internal tracker:
bash
curl -X GET http://<cn_ip>:8040/mem_tracker
This will show a tree of memory usage. Look for the compaction and metadata nodes. If Process is near the Limit, the internal safety mechanism is what's triggering your errors, effectively "guarding" the Pod limit.
Recommendation
To bridge the gap and let the process use more of the Pod's actual capacity:
1. Increase `mem_limit`: If you are confident the Pod has 10GB and nothing else is running on it, change the limit from 90% to 95% in cn.conf or via SQL:
sql
-- Example: Set to 9GB if your pod is 10GB
UPDATE information_schema.be_configs SET value = "9663676416" WHERE name = "mem_limit";
2. Explicitly set the Limit: Instead of a percentage, set a literal value (e.g., 8G) in your cn.conf so there is no ambiguity about what StarRocks considers "Full."
References
• administration/management/resource_management/Memory_management.md
• administration/management/BE_configuration.md
• administration/management/monitoring/Monitor_and_Alert.md
• administration/management/monitoring/metrics.md
• deployment/sr_operator.mdTravis (YaaaDingus)
09/22/2026, 7:31 PMRocky
09/22/2026, 7:32 PMUsed: 8.1GB, Limit: 8.1GB shows that StarRocks has reached its own internal ceiling, even if your Pod or VM has 32GB or 64GB of RAM available (the "75% headroom" you see).
Why this happens:
1. StarRocks' Internal Safety Valve: StarRocks manages its own memory using an internal MemTracker. If it hits the value set in its mem_limit configuration, it will fail tasks (like compaction or queries) to prevent a hard OOM crash of the entire process.
2. The "8.1GB" Mystery: Your limit 8697308774 is exactly 8.1 GB. This often happens because:
* Misdetection: In some container environments (especially with Cgroups v2), StarRocks may misdetect the available memory and default to a safe but small value.
* Hardcoded Config: The mem_limit in your cn.conf (or via a Helm chart/Operator) might be explicitly set to 8G or 25% of a larger node.
* Resource Groups: If you are using Resource Groups, the compaction task might be constrained by a group limit that is much smaller than the total system memory.
How to fix it:
You need to tell StarRocks it is allowed to use more of that "headroom."
1. Check the current config
Run this to see what StarRocks thinks the limit is and where it's coming from:
sql
SELECT * FROM information_schema.be_configs WHERE name = 'mem_limit';
2. Increase the Limit (Dynamic)
If the node has 32GB and you want StarRocks to use 90% of it, set it explicitly. You can use a percentage or a literal value:
sql
-- Set to 90% of the container/VM memory
UPDATE information_schema.be_configs SET value = "90%" WHERE name = "mem_limit";
-- OR set a literal value (e.g., 28GB)
UPDATE information_schema.be_configs SET value = "30064771072" WHERE name = "mem_limit";
3. Address "Ghost" Memory (Jemalloc Retained)
Sometimes the Used value in the error looks high (8GB) but your dashboard says the process is only using 2GB. This is because StarRocks' tracker includes *Retained Memory*—memory that the allocator (jemalloc) has requested from the OS but is currently sitting idle in a cache.
* To force StarRocks to be less "panicky" about this idle memory, you can adjust the memory_high_level (default 75%) which determines when it starts aggressively failing tasks.
Summary Recommendation
If you have 75% headroom on the host, your StarRocks mem_limit is simply set too low. Increase mem_limit to 90% in your cn.conf or via the UPDATE command above, and those "Memory of process exceed limit" errors will disappear.
References
• administration/management/resource_management/Memory_management.md
• administration/management/BE_configuration.md
• faq/resource_isolation_faq.md
• administration/management/monitoring/metrics.md
References
• administration/management/resource_management/Memory_management.md
• administration/management/monitoring/metrics.mdTravis (YaaaDingus)
09/22/2026, 7:33 PMRocky
09/22/2026, 7:34 PMtop or K8s metrics) reports RSS (Resident Set Size).
Here is why that discrepancy occurs and why it is triggering your compaction failure:
1. The "Allocator Cache" Gap (Jemalloc/Tcmalloc)
StarRocks uses a high-performance memory allocator (jemalloc). When StarRocks "frees" memory, the allocator often keeps that memory in its own internal pools (the freelist) rather than returning it to the Linux kernel immediately.
* The OS view (< 3GB): Linux sees that the process is no longer "touching" those pages, so it doesn't count them in the RSS or may have even reclaimed the physical pages if they were "dirty" but not active.
* StarRocks view (~9GB): StarRocks' internal MemTracker counts memory the moment it is requested from the allocator. If the allocator hasn't explicitly returned that memory to the OS, StarRocks still considers it "Used" by the process to avoid over-committing.
2. Jemalloc Metadata Tracking (v3.2.12+)
Starting in version 3.2.12, StarRocks introduced a jemalloc_tracker_daemon. It explicitly tracks jemalloc internal metadata and overhead. In some workloads, this metadata can grow significantly. If this tracker is active, it adds this overhead to the "Used" total, which is "invisible" memory that doesn't show up in standard process monitoring but is physically reserved.
3. "Virtual" Accounting (MemTracker)
StarRocks' MemTracker is hierarchical. It adds up the memory used by Queries, Loads, Compaction, and Caches.
* If there is an accounting error (e.g., memory is tracked but not untracked correctly in a specific code path), the tracker will "drift" upward while the actual physical memory usage remains low.
* Check for drift: You can verify this by visiting http://<CN_IP>:8040/mem_tracker. Look for a category that seems impossibly large compared to your actual workload.
4. Compaction "Peak" Spikes
The error happens during "read and decompress page." This is a high-memory-pressure moment.
* Compaction might request a massive block of memory for decompression.
* The MemTracker adds this request to the "Used" counter before the memory is actually used.
* If this request pushes the total to 8.69GB, the tracker immediately triggers the "Limit Exceeded" error and kills the task.
* Because the task was killed instantly, your monitoring tools (which usually sample every 10–30 seconds) never see the 1-millisecond spike; they only see the "steady state" of < 3GB.
How to resolve the discrepancy:
1. Force a Memory Release: You can tell the allocator to give memory back to the OS, which often "syncs" the tracker and the OS metrics:
bash
# Run this on the CN node
curl -X POST <http://localhost:8040/mem_tracker/release>
2. Verify the Tracker details: Compare the "Process" limit vs. sub-trackers:
bash
curl <http://localhost:8040/mem_tracker>
3. Adjust `memory_high_level`: If you want StarRocks to be less aggressive about failing tasks when it thinks it is full, you can increase memory_high_level (default is 75%) to 85% or 90% in cn.conf. This gives the "Peak" spikes more room to move before the safety valve kicks in.
In summary: StarRocks is failing the compaction because its internal ledger says it is out of money (memory), even if the bank account (the OS) looks like it has plenty. Reducing compaction "chunk" sizes (as suggested in the previous response) is the best way to stop these spikes from hitting that internal ledger limit.
References
• administration/management/resource_management/Memory_management.md
• administration/management/BE_configuration.mdRocky
09/22/2026, 7:34 PMTravis (YaaaDingus)
09/22/2026, 7:36 PMfree command or pod metrics? This seems ridiculousRocky
09/22/2026, 7:36 PMMemTracker.
* How it works: When a thread wants to run a compaction or a query, it "asks" the tracker: "I am about to allocate 1GB, is that okay?" The tracker adds 1GB to its internal counter immediately.
* The Discrepancy: If the code has a bug or a "drift" (where it forgets to subtract memory when it's done), or if it over-estimates how much it needs, the tracker's count will keep rising.
* The Result: The tracker thinks it's using 9GB (its software limit), so it kills the task. Meanwhile, the Linux kernel and your Pod metrics look at the actual physical pages (RSS) and see only 3GB.
2. Why the Tracker is "Over-Counting"
There are three common reasons for the 3x discrepancy you're seeing:
* Accounting Drift: This is a known issue in certain versions (like v3.1.x and v3.2.x). If a specific task (like a Hash Join or Compaction) doesn't perfectly "un-track" its memory, the tracker will report a high number forever until the process restarts.
* Virtual Reservation: Some allocators (like jemalloc) reserve large chunks of virtual address space. StarRocks' tracker sometimes counts these "reservations" as "Used" memory even before the RAM is physically touched.
* Metadata Overhead: Since v3.2.12, StarRocks explicitly tracks jemalloc metadata. In some cases, the internal overhead of managing memory can be reported as part of the process limit, which standard tools like free or top often ignore.
3. The Missing Release API
The reason you're seeing a 404 or "does not exist" for a release API is that memory reclamation in StarRocks is largely automatic and tied to two configuration watermarks:
* memory_high_level (Default 75%): When the tracker hits this, StarRocks tries to gracefully free caches.
* memory_urgent_level (Default 85%): When it hits this, it starts killing tasks aggressively.
How to fix it (Since the Tracker is Lying)
If your Pod metrics show 75% headroom, the most effective way to stop these "ridiculous" errors is to tell the software ledger to be less restrictive:
1. Increase the internal `mem_limit`: If your Pod has 16GB but the error says Limit: 8.1GB, StarRocks has misdetected your environment. Force it higher so the tracker has more "virtual" room:
sql
-- Set it to a value higher than what you actually have if you need to bypass a "drifting" tracker
ADMIN SET FRONTEND CONFIG ('mem_limit' = '95%');
-- Or for the BE/CN specifically:
UPDATE information_schema.be_configs SET value = "95%" WHERE name = "mem_limit";
2. Verify the specific culprit: Visit http://<BE_IP>:8040/memz. Look for the section "Actual memory used" vs "Bytes in page heap freelist." If the freelist is huge, the memory is "stuck" in the allocator and the tracker is counting it as used.
3. Check for Tracker Drift: Check http://<BE_IP>:8040/mem_tracker. If the sum of all sub-trackers (Query, Load, Compaction) is much smaller than the Process total, you are experiencing tracker drift, which usually requires a restart to reset the ledger.
Summary: You aren't crazy—the process is failing because it's hitting a calculated software cap that has drifted away from your actual hardware usage. Raising the mem_limit is the standard "escape hatch" for this.
References
• administration/management/resource_management/Memory_management.mdRocky
09/22/2026, 7:36 PMTravis (YaaaDingus)
09/22/2026, 7:37 PMRocky
09/22/2026, 7:37 PMUsed: 8.1GB, it is not measuring your RAM; it is reading a counter that StarRocks increments every time a thread asks for memory. If a piece of code forgets to "un-track" that memory when it’s finished, the counter stays high forever.
To prove this and find where the "missing" memory is, check these two specific internal pages on your CN/BE node:
1. The Smoking Gun: mem_tracker
Go to http://<CN_IP>:8040/mem_tracker.
* Look at the top-level "Process" tracker. It will show ~8.1GB.
* Now, look at the level 2 trackers (QueryPool, Load, Compaction, Metadata, etc.).
* The Discrepancy: If the sum of all sub-trackers is ~3GB, but the Process total is 8.1GB, you have Drift. The tracker has "leaked" accounting units, and StarRocks now thinks it is full.
2. The Allocator View: memz
Go to http://<CN_IP>:8040/memz.
* "Bytes in use by application": This is what StarRocks is actually using. It should match your < 3GB Pod metrics.
* "Bytes in page heap freelist": This is memory the allocator is holding but not using.
* If both these numbers are low, but the mem_tracker (from step 1) is still high, then the StarRocks accounting ledger is definitely broken.
Why is this happening?
* Version-Specific Bugs: There are documented bugs in v3.1.x and v3.2.x where specific tasks (like Cgroup v2 detection or jemalloc metadata tracking) cause the tracker to over-count.
* Jemalloc Metadata (v3.2.12+): A new daemon was added to track memory overhead. In some environments, this metadata tracker grows indefinitely, "consuming" your mem_limit without actually using physical RAM.
How to stop the "Ridiculous" behavior:
Since the tracker is essentially lying to the system, you have two options to stop it from killing your tasks:
1. The "Lies for Lies" Fix (Immediate):
If the tracker thinks it's using 8GB but it's only using 3GB, increase your mem_limit to something "impossible" like 200% or 100G. This doesn't actually give the process more RAM (the OS/K8s will still kill it if it hits the real physical limit), but it prevents the software tracker from hitting its own imaginary ceiling and killing your compaction tasks.
sql
UPDATE information_schema.be_configs SET value = "200%" WHERE name = "mem_limit";
2. The "Reset" (Short-term):
Restart the CN/BE process. This is currently the only way to reset a drifted MemTracker back to zero.
3. Disable Metadata Tracking (If on v3.2.12+):
If you see "jemalloc_metadata" taking up all the space in the tracker UI, try setting this in your cn.conf and restarting:
enable_jemalloc_memory_tracker = false
Summary: You are seeing a bug in the accounting system, not a real memory leak. Because StarRocks trust its internal counter more than the OS, it is committing "suicide" by killing tasks it actually has plenty of room to run.
References
• administration/management/resource_management/Memory_management.md
• administration/management/BE_configuration.md
• administration/management/monitoring/metrics.md
• faq/fe_mem_faq.md
• knowledge/trouble_shooting/fe_memory_problems.md
References
• administration/management/resource_management/Memory_management.mdRocky
09/22/2026, 7:37 PMTravis (YaaaDingus)
09/23/2026, 8:11 PMALTER TABLE table_name BASE COMPACTION and it initially lowers compaction, but then the compaction gets bad again. The data load rate isn't that high for these tables.Rocky
09/23/2026, 8:11 PMALTER TABLE ... BASE COMPACT is a "heavy" operation that merges all existing data versions into one. While it resets the score to its minimum, it is only a temporary fix if the underlying cause of version accumulation isn't addressed.
If your compaction score gets "bad" (e.g., >100) quickly even with a low data load rate, it is usually due to one of the following reasons:
1. The "Small Load" Trap
The Compaction Score is essentially a count of unmerged data versions (Rowsets) for a specific tablet.
* The Math: 1 Load Transaction = 1 Rowset Version.
* If you load data every 30 seconds, you create 120 versions in just one hour.
* Once a tablet has >100 versions, StarRocks considers it "unhealthy."
* Even if the total data size is small, the sheer number of versions forces the score up.
Solution: Increase your batch size or load interval. Aim for minutes rather than seconds between commits.
2. Excessive Bucket Count
If your table has too many buckets (e.g., 100 buckets for a 1GB table), every single load transaction must create a file for every bucket.
* This fragments your data into thousands of tiny files.
* Small files are much harder for the background Cumulative Compaction to merge effectively.
* Solution: Check your bucket count with SHOW CREATE TABLE. For small/medium tables, you usually only need a few buckets per BE/CN. If you have hundreds of buckets for a small table, consider re-creating it with fewer buckets or using Random Distribution (if not using Primary Key).
3. Cumulative Compaction is Stuck
StarRocks performs two types of background compaction:
1. Cumulative: Merges many small "new" rowsets into a larger "cumulative" rowset.
2. Base: Merges the cumulative rowset into the "base" data.
If your score stays low after a manual Base Compaction but then climbs past 100 again, it means Cumulative Compaction is not keeping up with your ingestion. It's failing to merge the small new files, so they just pile up until they hit the limit.
How to check:
sql
-- Check if compaction tasks are actually running or failing
SHOW PROC '/compactions';
-- Check the error message for specific partitions
SELECT * FROM information_schema.be_cloud_native_compactions
WHERE status != 'OK';
4. Primary Key Table Overhead
If you are using the Primary Key model, every UPDATE or DELETE also creates a new version. If you have a high frequency of small updates, the version count will skyrocket.
* Primary Key tables have a dedicated compaction thread. You can try increasing its concurrency in be.conf (or cn.conf for shared-data):
properties
# Increase compaction threads (standard is 4, try increasing if CPU allows)
compact_threads = 8
Recommended Next Steps:
1. Check for "many versions" error: Look at your FE/BE logs for too many tablet versions.
2. Verify Batch Size: Ensure you aren't doing "Point Inserts" (one row at a time) or loading more than once every 10–30 seconds.
3. Adjust Cumulative Thresholds: You can make background compaction more aggressive by decreasing the interval in `be.conf`:
properties
cumulative_compaction_check_interval_seconds = 2
4. Reduce Buckets: If SHOW PARTITIONS shows that your DataSize is small but MaxCS is high, your table is likely over-bucketed. Reducing buckets is the most permanent fix for high compaction scores on small/medium datasets.
References
• best_practices/primarykey_table.md
• table_design/table_types/primary_key_table.md
• administration/management/monitoring/metrics.md