Cassandra Adding Nodes
Adding nodes (bootstrapping) expands cluster capacity by introducing new nodes that automatically receive a portion of existing data through streaming.
Prerequisites
Section titled “Prerequisites”The following requirements must be met before adding a node:
Cluster State Requirements
Section titled “Cluster State Requirements”| Requirement | Verification | Rationale |
|---|---|---|
All nodes should show UN status | nodetool status | Bootstrap from degraded cluster increases risk; proceed with caution if necessary |
| No topology changes in progress | nodetool netstats | Only one topology change may occur at a time |
| No active repairs | nodetool netstats | Concurrent operations cause unpredictable behavior |
| Schema agreement | nodetool describecluster | Schema disagreement causes bootstrap failures |
# Pre-flight verificationnodetool status # All nodes UNnodetool describecluster # Single schema versionnodetool netstats # No active streamingnodetool compactionstats # No heavy compactionHardware Requirements
Section titled “Hardware Requirements”| Requirement | Rationale |
|---|---|
| Same or better specs as existing nodes | Uniform performance |
| Sufficient disk for expected data share | Node receives 1/N of cluster data |
| Network connectivity to all existing nodes | Gossip and streaming |
Software Requirements
Section titled “Software Requirements”| Requirement | Consequence if Violated |
|---|---|
| Same Cassandra version | Schema conflicts, potential data corruption |
| Same JVM version | Undefined behavior |
| Same partitioner | Node cannot join cluster |
| Compatible snitch | Topology awareness failures |
Network Requirements
Section titled “Network Requirements”| Port | Protocol | Purpose |
|---|---|---|
| 7000 | TCP | Internode communication (gossip, streaming) |
| 7001 | TCP | Internode communication (SSL, if enabled) |
| 9042 | TCP | CQL native transport |
| 7199 | TCP | JMX monitoring (optional) |
Behavioral Contract
Section titled “Behavioral Contract”Guarantees
Section titled “Guarantees”- New node receives data for its assigned token ranges from existing nodes
- Existing nodes continue serving client requests during bootstrap
- Data consistency is maintained (new node receives consistent replicas)
- Bootstrap is resumable if interrupted (with data directory cleared)
Token Assignment
Section titled “Token Assignment”| Configuration | Behavior |
|---|---|
num_tokens set (vnodes) | Tokens automatically assigned from random distribution |
initial_token set | Explicit token assignment (advanced) |
Token Count
The num_tokens value should match existing nodes. Cassandra 4.0+ defaults to 16 tokens; earlier versions defaulted to 256.
Failure Semantics
Section titled “Failure Semantics”| Scenario | Outcome | Recovery |
|---|---|---|
| Bootstrap completes | Node joins ring with full data | None required |
| Bootstrap interrupted | Partial data on new node | Clear data, restart |
| Source node fails during bootstrap | Streaming stalls | Wait for recovery or restart bootstrap |
| Network partition | Streaming fails | Resolve network, restart bootstrap |
| Disk full on new node | Bootstrap fails | Free space, clear data, restart |
Configuration
Section titled “Configuration”cassandra.yaml
Section titled “cassandra.yaml”The following settings must be configured on the new node:
# Must match existing cluster exactlycluster_name: 'ProductionCluster'
# Token configuration - must match existing nodesnum_tokens: 16 # Or 256 for older clusters
# Seed nodes - 2-3 existing stable nodes# The new node must NOT be listed as a seedseed_provider: - class_name: org.apache.cassandra.locator.SimpleSeedProvider parameters: - seeds: "10.0.1.1,10.0.1.2"
# This node's address - must be reachable by all other nodeslisten_address: 10.0.1.10rpc_address: 10.0.1.10
# Must match cluster configurationendpoint_snitch: GossipingPropertyFileSnitchpartitioner: org.apache.cassandra.dht.Murmur3Partitioner
# Enable bootstrap (default is true)auto_bootstrap: trueSeed Configuration
The new node must not be listed in its own seed list. Seeds should be 2-3 existing, stable nodes.
cassandra-rackdc.properties
Section titled “cassandra-rackdc.properties”For multi-datacenter deployments:
dc=dc1rack=rack1The datacenter and rack must match the intended topology placement.
Procedure
Section titled “Procedure”Step 1: Verify Cluster Health
Section titled “Step 1: Verify Cluster Health”On any existing node:
# All nodes must show UNnodetool status
# Schema must be in agreementnodetool describecluster
# No active streaming or repairsnodetool netstatsDo Not Proceed If
- Any node shows status other than
UN - Schema versions disagree
- Streaming or repair is in progress
Step 2: Prepare New Node
Section titled “Step 2: Prepare New Node”# Install Cassandra (same version as cluster)# Configure cassandra.yaml and cassandra-rackdc.properties
# Ensure data directories are emptysudo rm -rf /var/lib/cassandra/data/*sudo rm -rf /var/lib/cassandra/commitlog/*sudo rm -rf /var/lib/cassandra/saved_caches/*Step 3: Start Bootstrap
Section titled “Step 3: Start Bootstrap”sudo systemctl start cassandraThe node begins bootstrap automatically:
- Contacts seed nodes to learn cluster topology
- Gossip propagates new node information to all nodes
- Existing nodes stream data to new node
- New node transitions from
UJ(Joining) toUN(Normal)
Step 4: Monitor Progress
Section titled “Step 4: Monitor Progress”# Watch node status (from any node)watch -n 10 'nodetool status'
# Monitor streaming progress (on new node)nodetool netstats
# Watch logs for progress and errorstail -f /var/log/cassandra/system.log | grep -i "stream\|bootstrap"Expected state transitions:
| State | Code | Duration |
|---|---|---|
| Joining | UJ | Until streaming completes |
| Normal | UN | Bootstrap complete |
Step 5: Verify Completion
Section titled “Step 5: Verify Completion”# Node should show UN with datanodetool status
# Verify token ownershipnodetool ring | grep <new_node_ip>
# No active streamingnodetool netstatsStep 6: Run Cleanup
Section titled “Step 6: Run Cleanup”After bootstrap completes, existing nodes retain data that moved to the new node. Cleanup must run on all existing nodes:
# On EACH existing node (not the new node)# Run one node at a timenodetool cleanupSee Cleanup Operations for detailed guidance.
Duration Estimates
Section titled “Duration Estimates”Bootstrap duration depends on data volume and network throughput:
| Data to Stream | 200 Mbps (default) | 400 Mbps |
|---|---|---|
| 100 GB | 1-2 hours | 30-60 min |
| 500 GB | 4-8 hours | 2-4 hours |
| 1 TB | 8-16 hours | 4-8 hours |
| 2 TB | 16-32 hours | 8-16 hours |
Factors affecting duration:
- Network bandwidth between nodes
- Disk I/O throughput on source and target
- Number of source nodes (more nodes = more parallel streams)
- Stream throughput configuration
- Cluster load during bootstrap
Performance Tuning
Section titled “Performance Tuning”Increase Streaming Throughput
Section titled “Increase Streaming Throughput”Default streaming throughput is 200 Mbps. To accelerate bootstrap:
# On existing nodes - increase outbound streamingnodetool setstreamthroughput 400 # MB/s# On new node - cassandra.yamlstream_throughput_outbound_megabits_per_sec: 400Client Impact
Higher streaming throughput increases network and I/O load, potentially impacting client request latency. Use aggressive settings only during maintenance windows.
Cassandra 4.0+ Optimizations
Section titled “Cassandra 4.0+ Optimizations”# cassandra.yaml - stream entire SSTables (faster)stream_entire_sstables: trueRack-Aware Scaling
Section titled “Rack-Aware Scaling”When using NetworkTopologyStrategy with multiple racks, nodes must be added evenly across racks to maintain balanced data distribution.
The Imbalance Problem
Section titled “The Imbalance Problem”Cassandra places one replica per rack (when RF ≤ rack count). Uneven node distribution causes uneven load:
RF=3, 3 racks, uneven distribution:
Rack1: 3 nodes → each handles 1/3 of rack's replica loadRack2: 2 nodes → each handles 1/2 of rack's replica loadRack3: 1 node → handles 100% of rack's replica load ← OVERLOADEDBalanced Addition Rules
Section titled “Balanced Addition Rules”| Current State | Correct Addition | Incorrect Addition |
|---|---|---|
| 3 nodes (1 per rack) | Add 3 (1 to each rack) | Add 1 or 2 |
| 6 nodes (2 per rack) | Add 3 (1 to each rack) | Add 1 or 2 |
| 9 nodes (3 per rack) | Add 3 (1 to each rack) | Add 1 or 2 |
Formula: When adding nodes to a cluster with R racks, add in multiples of R to maintain balance.
Verification
Section titled “Verification”Check current rack distribution:
nodetool status
# Example balanced output (2 per rack):# Datacenter: dc1# UN 10.0.1.1 100 GB rack1# UN 10.0.1.2 100 GB rack1# UN 10.0.1.3 100 GB rack2# UN 10.0.1.4 100 GB rack2# UN 10.0.1.5 100 GB rack3# UN 10.0.1.6 100 GB rack3Check load distribution after adding:
# Load should be roughly equal across all nodesnodetool status | awk '/UN/ {print $3, $8}'Imbalanced Clusters
If an imbalanced state already exists, adding nodes to underrepresented racks is acceptable to restore balance. The goal is equal nodes per rack.
Adding Multiple Nodes
Section titled “Adding Multiple Nodes”Sequential Addition (Required)
Section titled “Sequential Addition (Required)”Nodes must be added one at a time when using vnodes (default):
# 1. Add first node, wait for UN status# 2. Add second node, wait for UN status# 3. Continue for all nodes# 4. Run cleanup on all original nodesWait times between additions:
| Cluster Size | Minimum Wait |
|---|---|
| < 10 nodes | Until previous node shows UN |
| 10-50 nodes | UN + 1 hour stabilization |
| 50+ nodes | UN + 2-4 hours stabilization |
Never Bootstrap Multiple Nodes Simultaneously
Concurrent bootstraps with vnodes cause token collisions and unpredictable data distribution. Add nodes strictly sequentially.
Manual Token Assignment (Advanced)
Section titled “Manual Token Assignment (Advanced)”Multiple nodes may bootstrap concurrently only with manually assigned, non-overlapping tokens:
# cassandra.yaml - explicit token (disables vnodes)num_tokens: 1initial_token: <calculated_token>This approach is complex and rarely necessary.
Troubleshooting
Section titled “Troubleshooting”Bootstrap Won't Start
Section titled “Bootstrap Won't Start”Symptoms: Node starts but doesn't appear in nodetool status
| Cause | Diagnosis | Solution |
|---|---|---|
| Cluster name mismatch | Check cluster_name in yaml | Fix name, clear data, restart |
| Seeds unreachable | nc -zv seed 7000 | Check firewall, network |
| Wrong listen_address | Log shows binding errors | Fix address in yaml |
| Data directory not empty | Check /var/lib/cassandra/data | Clear data directories |
# Check for errorsgrep -i "error\|failed" /var/log/cassandra/system.log | tail -50Bootstrap Stalled
Section titled “Bootstrap Stalled”Symptoms: Node stuck in UJ state, streaming shows no progress
| Cause | Diagnosis | Solution |
|---|---|---|
| Source nodes overloaded | High CPU/IO on sources | Reduce stream throughput |
| Network issues | Packet loss, timeouts | Fix network |
| Large partitions | Timeout errors in logs | Increase streaming_socket_timeout_in_ms |
| Disk full | df -h on new node | Free space |
# cassandra.yaml - for large partition timeoutsstreaming_socket_timeout_in_ms: 86400000 # 24 hoursBootstrap Failed
Section titled “Bootstrap Failed”Symptoms: Node crashed or stopped during bootstrap
Recovery:
# Clear partial datasudo systemctl stop cassandrasudo rm -rf /var/lib/cassandra/data/*sudo rm -rf /var/lib/cassandra/commitlog/*sudo rm -rf /var/lib/cassandra/saved_caches/*
# Restart bootstrapsudo systemctl start cassandraSee Troubleshooting for additional diagnostics.
Post-Bootstrap Tasks
Section titled “Post-Bootstrap Tasks”Required: Run Cleanup
Section titled “Required: Run Cleanup”Cleanup must run on all existing nodes after bootstrap:
# On each existing node (one at a time)nodetool cleanupRecommended: Update Monitoring
Section titled “Recommended: Update Monitoring”| Task | Action |
|---|---|
| Monitoring | Add new node to monitoring systems |
| Alerting | Update alert configurations |
| Backups | Add to backup schedules |
| Documentation | Update cluster inventory |
Optional: Update Seed List
Section titled “Optional: Update Seed List”If the new node should be a seed (only if replacing an unreliable seed):
# On ALL nodes, update cassandra.yamlseeds: "existing-seed1,existing-seed2,new-node"Rolling restart required for seed list changes to take effect.
Optional: Run Repair
Section titled “Optional: Run Repair”After cluster stabilizes:
# Repair the new node's token rangesnodetool repair -prRelated Documentation
Section titled “Related Documentation”- Cluster Management Overview - Operation selection guide
- Cleanup Operations - Post-bootstrap cleanup
- Scaling Operations - Adding multiple nodes
- Removing Nodes - Decommission procedures
- Troubleshooting - Diagnostic procedures