Apache Cassandra heap changes affect every read, write, and compaction on a node because the JVM heap shares physical memory with off-heap structures and the operating system page cache. A heap that is too small increases garbage-collection pressure, while a heap that is too large can take memory away from file cache and direct buffers.
Cassandra calculates heap at startup from /etc/cassandra/cassandra-env.sh unless static -Xms and -Xmx flags are already active in jvm-server.options. For the usual Cassandra 5 Java 11 or Java 17 G1GC path, set MAX_HEAP_SIZE and leave HEAP_NEWSIZE unset; HEAP_NEWSIZE belongs to older CMS tuning.
Choose the target after checking node RAM, workload, and recent garbage-collection behavior. Apache guidance keeps the heap at least 2 GB and no more than half of system RAM, and each restart should be rolled through one node at a time so the ring remains available while the new maximum is verified.
$ nodetool status Datacenter: datacenter1 ======================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns (effective) Host ID Rack UN 10.0.0.11 6.42 GiB 16 100.0% 8f4f6e2d-9f74-4f5a-a85f-43df5d4fcb21 rack1
Start with one UN node. If the ring already shows down, joining, leaving, or moving nodes, finish that maintenance before changing heap on another node.
$ nodetool info ID : 8f4f6e2d-9f74-4f5a-a85f-43df5d4fcb21 Gossip active : true Native Transport active: true Load : 6.42 GiB ##### snipped ##### Heap Memory (MB) : 514.18 / 1024.00 Off Heap Memory (MB) : 312.00 Data Center : datacenter1 Rack : rack1 Exceptions : 0
The value after the slash is the current maximum heap in megabytes.
$ sudoedit /etc/cassandra/jvm-server.options
If active -Xms or -Xmx lines are present, set both to the same target there or remove them before using MAX_HEAP_SIZE in /etc/cassandra/cassandra-env.sh. Commented lines beginning with # do not override cassandra-env.sh.
$ sudoedit /etc/cassandra/cassandra-env.sh
Package installs usually use /etc/cassandra/cassandra-env.sh. Tarball installs keep the same file under the extracted conf directory.
MAX_HEAP_SIZE="2G" # Leave HEAP_NEWSIZE unset when the node uses G1GC.
Replace 2G with the tested value for the node. Leave memory for the operating system page cache, direct memory, memtables, caches, and compaction work instead of assigning most RAM to the Java heap.
$ sudo systemctl restart cassandra
Restart one node at a time and wait for the node to return to the ring before changing the next node.
Related: How to check Apache Cassandra service status
$ sudo systemctl is-active cassandra active
$ nodetool status Datacenter: datacenter1 ======================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns (effective) Host ID Rack UN 10.0.0.11 6.42 GiB 16 100.0% 8f4f6e2d-9f74-4f5a-a85f-43df5d4fcb21 rack1
If the node does not return to UN, inspect /var/log/cassandra/system.log before moving to another node.
Related: How to view Apache Cassandra logs
$ nodetool info ID : 8f4f6e2d-9f74-4f5a-a85f-43df5d4fcb21 Gossip active : true Native Transport active: true Load : 6.42 GiB ##### snipped ##### Heap Memory (MB) : 623.98 / 2048.00 Off Heap Memory (MB) : 318.00 Data Center : datacenter1 Rack : rack1 Exceptions : 0
The maximum should match the configured heap after unit conversion. A 2G heap appears as about 2048.00 MB.