Tune JVM Memory#
Adjust the Java virtual machine (JVM) heap size for TheHive, Elasticsearch, and Cassandra based on your available system resources.
By default, Java automatically determines heap size from system memory. While suitable for small deployments, this behavior isn't recommended for production environments or when all components run on the same host, as multiple JVM processes compete for memory.
Defining heap sizes explicitly helps prevent resource contention and ensures predictable performance.
Maintenance window required
This procedure involves changing configuration files and restarting services. Schedule a maintenance window to prevent service disruption.
Inspect JVM flags and container resource limits#
Before adjusting heap sizes, inspect the current JVM flags and container resource limits to understand the baseline configuration. Run the following commands against any of the three services: TheHive, Cassandra, and Elasticsearch.
jcmd <service_pid> VM.flags
jcmd <service_pid> VM.info | grep -A 16 cgroup
Replace <service_pid> with the process ID of the concerned service.
Recommended memory allocation when all services share the same host#
When multiple services run on the same host, plan heap sizes across all of them before configuring each one individually. Multiple JVM processes competing for memory can cause resource contention or out-of-memory errors.
Cassandra: -Xms2g -Xmx4g -Xmn200m
Elasticsearch: -Xms3000m -Xmx3000m
TheHive: -Xms3000m -Xmx3000m -XX:MaxMetaspaceSize=400m -XX:ReservedCodeCacheSize=400m
Cassandra: -Xms4g -Xmx8g -Xmn400m
Elasticsearch: -Xms7000m -Xmx7000m
TheHive: -Xms7250m -Xmx7250m -XX:MaxMetaspaceSize=400m -XX:ReservedCodeCacheSize=400m
Cassandra: -Xms1g -Xmx3g -Xmn200m
Elasticsearch: -Xms2000m -Xmx2000m
TheHive: -Xms2000m -Xmx2000m -XX:MaxMetaspaceSize=400m -XX:ReservedCodeCacheSize=400m
Cortex: -Xms3g -Xmx3g
Cassandra: -Xms3g -Xmx6g -Xmn400m
Elasticsearch: -Xms5400m -Xmx5400m
TheHive: -Xms5400m -Xmx5400m -XX:MaxMetaspaceSize=400m -XX:ReservedCodeCacheSize=400m
Cortex: -Xms4g -Xmx4g
Configure JVM options for Cassandra#
Containerized deployments
For Docker and Kubernetes deployments, configure JVM options using environment variables instead.
-
Check if the
/etc/cassandra/jvm-server.optionsexists. If it doesn't, create it. -
Open the
/etc/cassandra/jvm-server.optionsfile using a text editor. -
In the
jvm-server.optionsfile, set the JVM options.Heap size guidelines for Cassandra
Heap allocation for Cassandra must not exceed 50% of the available RAM and should not be less than 2 GB. Available RAM refers to the memory remaining after accounting for the operating system and other services running on the same host.
-Xms<heap_size> -Xmx<heap_size> -Xmn<young_gen_size>Replace
<heap_size>with the desired heap size and<young_gen_size>with the desired young generation size.Xmssets the initial heap size,Xmxsets the maximum, andXmnsets the size of the young generation, where short-lived objects are allocated. -
Save your modifications in the
jvm-server.optionsfile. -
Restart Cassandra service.
sudo systemctl restart cassandra
Configure JVM options for Elasticsearch#
Containerized deployments
For Docker and Kubernetes deployments, configure JVM options using environment variables instead.
-
Check if the
/etc/elasticsearch/jvm.options.d/jvm.optionsexists. If it doesn't, create it. -
Open the
/etc/elasticsearch/jvm.options.d/jvm.optionsfile using a text editor. -
In the
jvm.optionsfile, set the JVM options.Heap size guidelines for Elasticsearch
Heap allocation for Elasticsearch must not exceed 50% of the available RAM. Available RAM refers to the memory remaining after accounting for the operating system and other services running on the same host.
-Dlog4j2.formatMsgNoLookups=true -Xms<heap_size> -Xmx<heap_size>Replace
<heap_size>with the desired heap size.Xmssets the initial heap size, andXmxthe maximum heap size.Set initial and maximum heap to the same value
Set
-Xmsand-Xmxto the same value to prevent heap resizing at runtime and reduce CPU overhead. -
Save your modifications in the
jvm.optionsfile. -
Restart Elasticsearch service.
sudo systemctl restart elasticsearch
Configure JVM options for TheHive#
Containerized deployments
For Docker and Kubernetes deployments, configure JVM options using environment variables instead.
-
Open the
/etc/default/thehivefile using a text editor. -
Uncomment the
JAVA_OPTSvariable. -
Enter
-Xms<heap_size> -Xmx<heap_size> -XX:MaxMetaspaceSize=<metaspace_size> -XX:ReservedCodeCacheSize=<code_cache_size>as the value.Heap size guidelines for TheHive
Heap allocation for TheHive service must not exceed 60% of the available RAM. Available RAM refers to the memory remaining after accounting for the operating system and other services running on the same host.
Replace
<heap_size>with the desired heap size.Set initial and maximum heap to the same value
Set
-Xmsand-Xmxto the same value to prevent heap resizing at runtime and reduce CPU overhead.Replace
<metaspace_size>with the desired Metaspace limit.Replace
<code_cache_size>with the desired code cache limit. -
Save your modifications.
-
Restart TheHive service.
sudo systemctl restart thehive
Diagnose persistent memory pressure#
If memory issues persist after adjusting heap sizes, use the following commands to investigate the root cause.
Check heap usage and run garbage collection (GC)#
PID=$(ps aux | grep 'thehive' | awk '{print $2}' | head -n1)
jcmd $PID GC.heap_info
jcmd $PID GC.run
jcmd $PID GC.heap_info
Compare the used heap before and after GC:
- Heap drops after GC: temporary pressure, not a leak
- Heap stays high after GC and grows over time: possible memory leak, unbounded cache, or processing backlog
Monitor heap over time#
PID=$(ps aux | grep 'thehive' | awk '{print $2}' | head -n1)
for i in $(seq 1 150); do
date '+%Y-%m-%d %H:%M:%S' >> heap_info.txt
sudo jcmd $PID GC.heap_info >> heap_info.txt
sleep 1
done
For a full observability setup, see Set Up Monitoring for TheHive with Prometheus and Grafana.
Check Java process resource usage#
top -c -p $(ps aux | grep 'java' | awk '{print $2}' | paste -sd ',') -n 1
If top is not available, use ps aux | grep 'java' instead. Note that this shows cumulative CPU usage since process start, not instantaneous usage.