Skip to main content

Performance Tuning & Production Operations

Module Duration: 10-12 hours Learning Style: Deep Technical + Hands-On Tuning + Production War Stories Outcome: Operate Cassandra clusters at peak performance in production environments

Introduction: The Production Reality

Running Cassandra in production is vastly different from development:
  • Development: Single node, small dataset, tolerant of restarts
  • Production: 50+ nodes, multi-TB per node, 24/7 uptime, millisecond SLAs
This module covers everything you need to run Cassandra successfully in production: JVM tuning, OS configuration, monitoring, capacity planning, and troubleshooting real-world issues.

Part 1: The JVM - Cassandra’s Foundation

Cassandra runs on the Java Virtual Machine (JVM). JVM performance directly impacts Cassandra performance, especially around garbage collection (GC).

Why GC Matters

Problem: Cassandra keeps data in memory (MemTables, caches). When JVM runs GC:
  • Stop-the-world pauses: Application threads freeze
  • Pauses > 1 second → timeouts, failed requests
  • Pauses > 10 seconds → nodes marked as DOWN by failure detector
Goal: Keep GC pauses < 200ms

Heap Size Configuration

Cassandra’s heap is split into two regions:
Sizing Rules:
Why These Limits? Real Example:

Garbage Collection Algorithms

Cassandra supports three main GC algorithms: Best For: Cassandra 3.0+, default choice Configuration:
How G1GC Works:
Tuning for Read-Heavy:
Tuning for Write-Heavy:

2. CMS (Concurrent Mark Sweep) - Legacy

Best For: Cassandra 2.x (deprecated in Cassandra 3.0+)
Issues:
  • Fragmentation in Old Gen → Full GC (5-10 second pauses!)
  • Deprecated in Java 9+

3. ZGC / Shenandoah - Experimental

Best For: Cassandra 4.0+, Java 11+, cutting-edge deployments
Benefits:
  • Sub-10ms pauses even with 100GB heaps!
  • Still experimental for Cassandra

GC Logging and Monitoring

Enable GC Logging:
Analyze GC Logs:
Breakdown:
  • Pause Young: Young generation collection
  • 2048M->512M: Heap before → after GC
  • (8192M): Total heap size
  • 45.678ms: Pause duration (monitor this!)
Tools for GC Analysis:
  1. GCViewer (GUI):
  1. GCEasy (Web-based):
Key Metrics to Watch:
  • Pause time p99: Should be < 200ms
  • Pause frequency: Young GC every 5-10 seconds is normal
  • Full GC events: Should be 0! Any Full GC is a red flag

Common GC Issues

Issue 1: Frequent Full GCs

Symptoms:
Causes:
  • Heap too small
  • Memory leak (improper cache configuration)
  • Large object allocation (huge queries)
Solutions:

Issue 2: Long Young GC Pauses

Symptoms:
Cause: Young gen too large Solution:

Issue 3: Memory Pressure

Symptoms:
  • Constant GC activity
  • nodetool tpstats shows dropped mutations
  • Heap constantly near max
Diagnosis:
Solutions:

Part 2: Operating System Tuning

Disk I/O Configuration

Cassandra is I/O intensive. OS settings massively impact performance.

File System Choice

Mount Options (XFS):
Why These Options?
  • noatime: Don’t update access time (reduces writes)
  • nodiratime: Don’t update directory access time
  • nobarrier: Disable write barriers (safe with battery-backed RAID)

I/O Scheduler

For SSDs:
For HDDs:

Readahead

Default: Often 8KB (too small for Cassandra)

Linux Kernel Settings

Critical sysctl Settings:
Apply Settings:

User Limits

Cassandra opens many files simultaneously:
Verify:

Swap Configuration

Philosophy: Minimize swap, but don’t disable entirely. Why Not Disable Swap?
  • Linux kernel may OOM-kill Cassandra if no swap
  • Small swap (1-2GB) acts as emergency overflow
Configuration:

Transparent Huge Pages (THP)

Issue: THP causes GC pauses and memory fragmentation. Disable THP:

CPU Governor

For Performance:

Part 3: Cassandra Configuration Tuning

Compaction Strategy Selection

Choosing the right compaction strategy is critical for performance.

STCS (Size-Tiered Compaction Strategy)

Best For: Write-heavy, time-series data, small tables How It Works:
Configuration:
Pros:
  • Fast writes (less compaction overhead)
  • Simple, predictable
Cons:
  • Read amplification (query may touch many SSTables)
  • Temporary disk space = 2x data size during compaction

LCS (Leveled Compaction Strategy)

Best For: Read-heavy, frequently updated data How It Works:
Configuration:
Pros:
  • Low read amplification (90% reads touch 1 SSTable)
  • Predictable disk space usage
Cons:
  • More compaction overhead (impacts writes)
  • More I/O intensive

TWCS (Time Window Compaction Strategy)

Best For: Time-series data with TTL How It Works:
Configuration:
Pros:
  • Ultra-fast TTL deletion (drop entire SSTable)
  • Minimal read amplification for time-range queries
Cons:
  • Only suitable for time-series with TTL
Comparison Table:

MemTable Configuration

MemTables are in-memory write buffers. Tuning them balances memory vs. flush frequency.
Trade-offs: Recommendation: Default is usually good. Only adjust if:
  • Many small writes: Increase MemTable size (reduce flush frequency)
  • Memory pressure: Decrease MemTable size

Cache Configuration

Cassandra has three caches:

1. Key Cache

Purpose: Cache partition key → SSTable mapping (avoid Bloom filter checks) Configuration:
When to Use:
  • Read-heavy workloads with hot partitions
  • Queries by primary key
When to Disable:
  • Write-heavy workloads
  • Cold data (rarely queried)

2. Row Cache

Purpose: Cache entire rows (most aggressive caching) Configuration:
Warning: Row cache is dangerous:
  • Consumes heap (increases GC pressure)
  • Only helps if reading exact same rows repeatedly
  • Most production clusters disable this
When to Use: Small, frequently-read tables (e.g., configuration)

3. Counter Cache

Purpose: Cache counter column values (counter tables only) Configuration:
Enable Per Table:

Commit Log Tuning

CommitLog is Cassandra’s write-ahead log. Two Modes:
  1. Periodic (default):
  • Pros: High write throughput
  • Cons: Up to 10 seconds of data loss on crash
  1. Batch:
  • Pros: Minimal data loss (2ms window)
  • Cons: 30-50% lower write throughput
Disk Configuration:
Best Practice: Use separate SSD for CommitLog if using HDDs for data.

Concurrent Operations

Control thread pool sizes:
Tuning:
  • More CPU cores: Increase concurrent_reads/writes
  • More disks: Increase concurrent_compactors
  • Memory constrained: Decrease to reduce overhead

Part 4: Monitoring and Observability

Key Metrics to Monitor

1. System Metrics

CPU:
Target: < 80% average, < 95% peak Disk I/O:
Network:

2. JVM Metrics

Heap Usage:
GC Metrics:
Target: Max GC < 200ms

3. Cassandra Metrics

Thread Pool Stats:
Critical: Dropped messages should be 0! Table Statistics:
Compaction Stats:
Pending compactions should stay low (< 20). High pending = falling behind.

4. Performance Metrics

Latency:
Targets:
  • p50 < 5ms
  • p95 < 20ms
  • p99 < 50ms
Throughput:

Monitoring Tools

Architecture:
Setup:
  1. Install JMX Exporter:
  1. Configure JMX Exporter (cassandra_jmx.yml):
  1. Add to JVM Options:
  1. Configure Prometheus (prometheus.yml):
  1. Import Grafana Dashboard:

2. DataStax OpsCenter

Commercial tool with free tier:
Features:
  • Visual cluster topology
  • Performance graphs
  • Repair scheduling
  • Backup management

3. Nodetool (Built-in)

Quick Checks:

Alert Thresholds

Critical Alerts: Warning Alerts:

Part 5: Capacity Planning

Disk Capacity

Formula:
Compaction Overhead:
  • STCS: 50% (2x data during compaction)
  • LCS: 10% (1.1x data)
  • TWCS: 20% (1.2x data)
Example:

Memory Capacity

Formula:
Example (64GB RAM):
Why Large OS Cache?
  • Cassandra relies on OS page cache for SSTable caching
  • Larger cache = fewer disk reads = better performance

CPU Capacity

Rule of Thumb: 1 CPU core per 1-2 TB of data Example:

Network Capacity

Formula:
Example:

Scaling Triggers

When to Add Nodes: Scaling Example:

Part 6: Backup and Disaster Recovery

Snapshot-Based Backups

How Snapshots Work:
Create Snapshot:
Snapshot Location:
List Snapshots:
Delete Snapshot:

Incremental Backups

Enable Incremental Backups:
How It Works:
Backup Location:
Backup Strategy:

Backup to External Storage

Script Example (S3):
Automate with Cron:

Restore from Backup

Full Restore Process:
  1. Stop Cassandra:
  1. Clear existing data:
  1. Restore snapshot:
  1. Fix ownership:
  1. Restart Cassandra:
  1. Run repair (important!):

Point-in-Time Recovery

Requirements:
  • Full snapshot
  • Incremental backups
  • CommitLog archives
CommitLog Archiving:
Archive Script:

Part 7: Troubleshooting Production Issues

Issue 1: High Read Latency

Symptoms:
Diagnosis Steps:
  1. Check SSTable Count:
Solution: Switch to LCS or run compaction:
  1. Check for Wide Partitions:
Solution: Redesign data model (split partition)
  1. Check Disk I/O:
Solution: Add nodes or upgrade to SSDs
  1. Check for Tombstones:
Solution: Run repair or adjust gc_grace_seconds

Issue 2: Write Timeouts

Symptoms:
Diagnosis:
  1. Check Dropped Mutations:
Cause: Nodes can’t keep up with write load
  1. Check Pending Compactions:
Cause: Compaction can’t keep up Solutions:
  1. Check GC Pauses:
Cause: Heap pressure Solution: Reduce MemTable size or increase heap

Issue 3: Node Marked as DOWN (But It’s Running)

Symptoms:
Diagnosis:
  1. Check Failure Detector:
  1. Check for GC Pauses:
Cause: GC pause exceeded failure detector threshold Solutions:

Issue 4: Disk Full

Symptoms:
Diagnosis:
Solutions:
  1. Delete Old Snapshots:
  1. Clean Incremental Backups:
  1. Compact Tables:
  1. Add Nodes (long-term solution)

Issue 5: Schema Mismatch

Symptoms:
Diagnosis:
  • Node 10.0.1.12 has different schema
  • Gossip not propagating schema updates
Solutions:
  1. Force Schema Reset:
  1. Restart Gossip:
  1. Rolling Restart (last resort):

Part 8: Advanced Production Topics

Multi-DC Latency Optimization

Problem: Cross-DC writes add 100-200ms latency Solution: Use LOCAL_QUORUM for writes:
Why: Write only waits for local DC acknowledgment, remote DC replicates asynchronously. Trade-off: Remote DC may lag by seconds/minutes during network issues.

Read Consistency Tuning

Scenario: Reads occasionally return stale data Diagnosis: Repair not running frequently enough Solutions:
  1. Increase Read Repair Chance:
  1. Use Higher Consistency Level:
  1. Run Repair More Frequently:

Handling Large Partitions

Problem: Partition > 100MB causes:
  • High read latency
  • Timeouts
  • OOM errors
Detection:
Solutions:
  1. Redesign Data Model (best):
  1. Add Compaction Threshold:

Connection Pool Tuning (Driver-Side)

Python Driver:
Java Driver:

Part 9: Performance Checklist

Pre-Production Checklist

  • Hardware
    • SSDs for data and commitlog
    • 10 Gbps network
    • 64GB+ RAM per node
    • 8+ CPU cores per node
  • OS Configuration
    • XFS filesystem with noatime,nodiratime
    • Swap disabled or swappiness=1
    • THP disabled
    • I/O scheduler: noop (SSD) or deadline (HDD)
    • Readahead: 8-16MB
    • File descriptor limits: 65536
    • CPU governor: performance
  • JVM Configuration
    • Heap: 8GB max
    • G1GC enabled
    • GC logging enabled
    • GC pause target: 200ms
  • Cassandra Configuration
    • Compaction strategy matches workload
    • Concurrent operations tuned
    • Caches configured
    • CommitLog on separate disk (if HDD)
    • NetworkTopologyStrategy for multi-DC
  • Monitoring
    • Prometheus + Grafana or OpsCenter
    • Alerts configured
    • Log aggregation (e.g., ELK stack)
  • Backup
    • Snapshot schedule configured
    • Incremental backups enabled
    • Restore procedure tested
  • Repair
    • Automated repair schedule (weekly)
    • Repair monitoring

Performance Testing

Load Testing Tools:
  1. cassandra-stress (built-in):
  1. NoSQLBench:
Key Metrics to Capture:
  • Throughput (ops/sec)
  • Latency (p50, p95, p99, p999)
  • Error rate
  • Resource utilization (CPU, RAM, disk, network)

Part 10: Hands-On Exercises

Exercise 1: JVM Tuning

Scenario: Node experiencing 2-second GC pauses Task:
  1. Analyze GC log: cat /var/log/cassandra/gc.log
  2. Identify problem (heap too large? Young gen too large?)
  3. Adjust JVM settings in jvm11-server.options
  4. Restart and monitor improvements
Expected: GC pauses < 200ms after tuning

Exercise 2: Compaction Strategy Comparison

Task:
  1. Create three identical tables with different compaction strategies (STCS, LCS, TWCS)
  2. Load 10GB of data into each
  3. Run mixed read/write workload with cassandra-stress
  4. Compare SSTable count, read latency, write latency
Questions:
  • Which strategy has lowest SSTable count?
  • Which strategy has best read latency?
  • Which strategy has best write throughput?

Exercise 3: Monitoring Setup

Task:
  1. Install Prometheus + Grafana
  2. Configure JMX exporter on Cassandra nodes
  3. Import Cassandra dashboard
  4. Create custom alerts for:
    • GC pause > 500ms
    • Dropped mutations > 0
    • Pending compactions > 20

Exercise 4: Backup and Restore

Task:
  1. Create snapshot of my_keyspace
  2. Upload to S3 (or local directory)
  3. Drop table: DROP TABLE my_keyspace.users;
  4. Restore from snapshot
  5. Verify data integrity

Exercise 5: Troubleshoot Slow Queries

Scenario: Query taking 5 seconds Task:
  1. Analyze trace output
  2. Identify bottleneck (tombstones? large partition? SSTable count?)
  3. Apply fix (repair? compaction? data model change?)
  4. Verify improvement

Summary & Production Best Practices

JVM:
  • Heap: 8GB max (25% of RAM)
  • GC: G1GC with 200ms pause target
  • Monitor GC logs continuously
OS:
  • SSDs for all storage
  • XFS with noatime
  • Disable THP and swap
  • I/O scheduler: noop
Cassandra:
  • Compaction strategy matches workload
  • Run repair weekly (within gc_grace_seconds)
  • Use LOCAL_QUORUM for multi-DC
  • Monitor: GC, tpstats, compaction, latency
Capacity Planning:
  • 1 core per 1-2TB data
  • 64GB+ RAM (8GB heap + 48GB OS cache)
  • Disk: 50% headroom for compaction
  • Network: 10 Gbps minimum
Backup:
  • Daily snapshots to external storage
  • Incremental backups enabled
  • Test restore procedures regularly
Troubleshooting:
  • High reads → Check SSTable count, tombstones
  • High writes → Check pending compactions, GC
  • Timeouts → Check dropped messages, disk I/O
  • Node down → Check failure detector, GC pauses

What’s Next?

Module 7: Capstone Project - Building a Production System

Apply everything you’ve learned to design and implement a real-world Cassandra application at scale