Skip to content

AxonOps — AI-Native Control Plane for Open Source Data Platforms

sstableloader

Bulk loads SSTables from a directory into a live Cassandra cluster.


Terminal window
sstableloader [options] <dir_path>

sstableloader streams SSTable files from a local directory into a running Cassandra cluster. It reads SSTables from disk and uses Cassandra's streaming protocol to distribute the data to the appropriate nodes based on the cluster's token ranges.

This tool is essential for:

  • Restoring data from snapshots to a different cluster
  • Migrating data between clusters
  • Bulk loading externally generated SSTables
  • Disaster recovery when rebuilding a cluster

Unique Among SSTable Tools

Unlike most SSTable tools, sstableloader connects to a running Cassandra cluster. The source node (where the tool runs) does not need Cassandra running, but the target cluster must be operational.


sstableloader Processsstableloader ProcessSource Machine/load_dir/keyspace/table/Target ClustersstableloaderData.dbIndex.dbFilter.dbNode 1Token: 0-33Node 2Token: 34-66Node 3Token: 67-991. Reads SSTable files from <dir_path>2. Contacts cluster via -d nodes3. Discovers ring topology4. Determines partition ownership5. Streams to appropriate nodes6. Each node receives its dataStream partitions(tokens 0-33)Stream partitions(tokens 34-66)Stream partitions(tokens 67-99)

The directory path must follow Cassandra's data directory structure:

<base_path>/<keyspace>/<table>/
Examples:
/tmp/restore/my_keyspace/users/ # Correct - plain table name
/tmp/restore/my_keyspace/users-a1b2c3d4e5f6g7h8/ # Correct - table with UUID suffix
/var/backup/cycling/cyclist_name/ # Correct
/restore/my_keyspace/my_table/snapshots/ # Incorrect - extra directory level

On-Disk Table Directory Names

Cassandra stores tables with UUID suffixes (e.g., users-a1b2c3d4e5f6g7h8). When loading from live data or snapshots, the full directory name with UUID is accepted. Use -k and -tb options to override target keyspace/table if names differ.

The tool uses the directory names to determine the target keyspace and table:

Terminal window
# This path:
/tmp/load/my_keyspace/my_table/nb-1-big-Data.db
# Loads into:
# Keyspace: my_keyspace
# Table: my_table

ArgumentDescription
dir_pathPath to directory containing SSTable files. Must follow <keyspace>/<table>/ structure.

OptionDescription
-d, --nodes <hosts>Comma-separated list of initial hosts for ring discovery (required)
OptionDescription
-u, --username <user>Username for authentication
-pw, --password <password>Password for authentication
-ap, --auth-provider <class>Custom auth provider class
-p, --port <port>Native transport port (default: 9042)
-sp, --storage-port <port>Storage port for streaming (default: 7000)
OptionDescription
--throttle-mib <MiB/s>Throttle streaming speed in MiB per second
--inter-dc-throttle-mib <MiB/s>Throttle for inter-datacenter streaming
--entire-sstable-throttle-mib <MiB/s>Throttle for entire-SSTable streaming
--entire-sstable-inter-dc-throttle-mib <MiB/s>Inter-DC throttle for entire-SSTable streaming
-cph, --connections-per-host <n>Number of concurrent connections per host
OptionDescription
-k, --target-keyspace <name>Override target keyspace (different from directory name)
-tb, --target-table <name>Override target table (different from directory name)
OptionDescription
-f, --conf-path <path>Path to cassandra.yaml. Reads stream_throughput_outbound, client_encryption_options, and server_encryption_options
--keystore <path>Path to SSL keystore
--keystore-password <pass>Keystore password
--truststore <path>Path to SSL truststore
--truststore-password <pass>Truststore password
--ssl-protocol <protocol>SSL protocol (e.g., TLSv1.2)
--ssl-ciphers <ciphers>Comma-separated list of SSL ciphers
OptionDescription
-i, --ignore <hosts>Comma-separated list of hosts to ignore during streaming
--no-progressSuppress progress output
-v, --verboseEnable verbose output

Terminal window
# Load SSTables into cluster
sstableloader -d 192.168.1.10,192.168.1.11 /tmp/restore/my_keyspace/my_table/
Terminal window
# Load with username/password
sstableloader -d node1,node2,node3 \
-u cassandra \
-pw cassandra \
/backup/my_keyspace/users/
Terminal window
# Limit streaming to 100 MiB/s to prevent overwhelming the cluster
sstableloader -d node1,node2 \
--throttle-mib 100 \
/restore/my_keyspace/my_table/
Terminal window
# Method 1: Using cassandra.yaml for SSL settings
sstableloader -d node1,node2 \
-f /etc/cassandra/cassandra.yaml \
/restore/my_keyspace/my_table/
# Method 2: Explicit SSL parameters
sstableloader -d node1,node2 \
--keystore /path/to/keystore.jks \
--keystore-password secret \
--truststore /path/to/truststore.jks \
--truststore-password secret \
--ssl-protocol TLSv1.2 \
/restore/my_keyspace/my_table/
Terminal window
# Increase parallelism with more connections per host
sstableloader -d node1,node2,node3 \
--connections-per-host 8 \
/restore/my_keyspace/large_table/
Terminal window
# Skip streaming to a problematic node
sstableloader -d node1,node2,node3 \
-i node3 \
/restore/my_keyspace/my_table/

restore_from_snapshot.sh
#!/bin/bash
SNAPSHOT_NAME="daily_backup"
KEYSPACE="my_keyspace"
TABLE="my_table"
NODES="node1,node2,node3"
RESTORE_DIR="/tmp/restore"
# 1. Create directory structure
mkdir -p ${RESTORE_DIR}/${KEYSPACE}/${TABLE}
# 2. Copy snapshot files (from backup location)
cp /backup/${SNAPSHOT_NAME}/${KEYSPACE}/${TABLE}/*.db \
${RESTORE_DIR}/${KEYSPACE}/${TABLE}/
# 3. Verify schema exists in target cluster
cqlsh node1 -e "DESCRIBE TABLE ${KEYSPACE}.${TABLE};"
# 4. Load data
sstableloader -d ${NODES} ${RESTORE_DIR}/${KEYSPACE}/${TABLE}/
# 5. Cleanup
rm -rf ${RESTORE_DIR}
migrate_table.sh
#!/bin/bash
SOURCE_DATA="/var/lib/cassandra/data/old_keyspace/old_table-uuid"
TARGET_KEYSPACE="new_keyspace"
TARGET_TABLE="new_table"
TARGET_NODES="newcluster1,newcluster2,newcluster3"
STAGING="/tmp/migration"
# 1. Create staging directory with target keyspace/table names
mkdir -p ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}
# 2. Copy SSTables (ensure table is not being compacted)
nodetool flush old_keyspace old_table
cp ${SOURCE_DATA}/*Data.db ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/
cp ${SOURCE_DATA}/*Index.db ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/
cp ${SOURCE_DATA}/*Filter.db ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/
cp ${SOURCE_DATA}/*Statistics.db ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/
cp ${SOURCE_DATA}/*Summary.db ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/
cp ${SOURCE_DATA}/*TOC.txt ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/
cp ${SOURCE_DATA}/*CompressionInfo.db ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/ 2>/dev/null
cp ${SOURCE_DATA}/*Digest.crc32 ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/ 2>/dev/null
# 3. Load into target cluster
sstableloader -d ${TARGET_NODES} \
--throttle-mib 200 \
${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/
# 4. Verify row count
echo "Source count:"
cqlsh source_node -e "SELECT COUNT(*) FROM old_keyspace.old_table;"
echo "Target count:"
cqlsh newcluster1 -e "SELECT COUNT(*) FROM ${TARGET_KEYSPACE}.${TARGET_TABLE};"

When loading SSTables created by external tools (like Spark):

Terminal window
# SSTables must be in correct format and have matching schema
sstableloader -d node1,node2,node3 \
--verbose \
/generated_data/my_keyspace/my_table/

Schema Must Exist First

The target keyspace and table must exist in the cluster before running sstableloader. The tool does not create schemas.

Terminal window
# Verify schema exists
cqlsh node1 -e "DESCRIBE KEYSPACE my_keyspace;"
cqlsh node1 -e "DESCRIBE TABLE my_keyspace.my_table;"
# If restoring, recreate schema first
cqlsh node1 -f /backup/schema.cql

The SSTable schema must be compatible with the target table schema:

ScenarioResult
Exact schema matchSuccess
Target has additional columnsSuccess (new columns will be null)
Target missing columnsFailure
Different column typesFailure
Different primary keyFailure

FactorImpactTuning
Network bandwidthHighUse --throttle-mib to prevent saturation
Connections per hostMediumIncrease --connections-per-host
Cluster sizeMediumMore nodes = parallel streaming
SSTable sizeLowTool handles any size
Disk I/O on sourceMediumUse SSD for staging directory

Small dataset (< 10 GB):

Terminal window
sstableloader -d nodes /path/to/data/
# Default settings usually sufficient

Medium dataset (10-100 GB):

Terminal window
sstableloader -d nodes \
--connections-per-host 4 \
--throttle-mib 200 \
/path/to/data/

Large dataset (> 100 GB):

Terminal window
sstableloader -d nodes \
--connections-per-host 8 \
--throttle-mib 500 \
/path/to/data/
# Consider loading during off-peak hours
# Monitor cluster health during load

Terminal window
sstableloader -d nodes -v /path/to/data/
# Sample output:
# Established connection to initial hosts
# Opening sstables and calculating sections to stream
# Streaming relevant part of /path/to/data/nb-1-big-Data.db to [/192.168.1.10, /192.168.1.11]
# progress: [node1]0:0/1 0% [node2]0:0/1 0% total: 0% 0.0 MB/s
# progress: [node1]0:1/1 100% [node2]0:1/1 100% total: 100% 45.2 MB/s
# Summary statistics:
# Connections per host: 1
# Total files transferred: 2
# Total bytes transferred: 156.3 MB
# Total duration: 3.5 s
# Average throughput: 44.7 MB/s
Terminal window
# On target nodes, watch streaming activity
nodetool netstats
# Watch for compaction backlog
nodetool compactionstats
# Monitor load on target nodes
nodetool tpstats | grep -i stream

Terminal window
# Error: Failed to connect to node1:9042
# Check 1: Is Cassandra running on target nodes? (run on the target node via SSH)
ssh node1 "nodetool status"
# Check 2: Is native transport enabled?
ssh node1 "nodetool statusbinary"
# Check 3: Firewall allows port 9042?
nc -zv node1 9042
# Check 4: Correct port specified?
sstableloader -d node1 -p 9142 /path/ # If using non-default port
Terminal window
# Error: Authentication error
# Verify credentials work
cqlsh node1 -u username -p password
# Use correct authentication options
sstableloader -d node1 -u username -pw password /path/
Terminal window
# Error: Unknown keyspace/table
# Verify schema exists
cqlsh node1 -e "DESCRIBE KEYSPACE my_keyspace;"
# Check directory structure matches keyspace/table names
ls /path/to/load/
# Should show: my_keyspace/
ls /path/to/load/my_keyspace/
# Should show: my_table/
Terminal window
# Error: SSL handshake failed
# Method 1: Use cassandra.yaml with SSL config
sstableloader -d node1 -f /etc/cassandra/cassandra.yaml /path/
# Method 2: Verify keystore/truststore
keytool -list -keystore /path/to/keystore.jks
# Method 3: Check SSL protocol compatibility
sstableloader -d node1 \
--ssl-protocol TLSv1.2 \
--keystore /path/to/keystore.jks \
--keystore-password pass \
--truststore /path/to/truststore.jks \
--truststore-password pass \
/path/
Terminal window
# Error: Streaming timed out
# Reduce throughput to prevent overwhelming nodes
sstableloader -d nodes --throttle-mib 50 /path/
# Check cluster health (run on the target node via SSH)
ssh node1 "nodetool status"
ssh node1 "nodetool tpstats"
Terminal window
# Error: Missing component files
# Verify all SSTable components present
ls /path/to/keyspace/table/
# Need at minimum: Data.db, Index.db, Filter.db, Statistics.db, Summary.db, TOC.txt
# Copy all components for each SSTable
cp /source/*-1-big-* /dest/

sstableloader Guidelines

  1. Verify schema first - Table must exist before loading
  2. Use throttling - Prevent overwhelming target cluster
  3. Monitor during load - Watch cluster health metrics
  4. Load during off-peak - Reduce impact on production traffic
  5. Verify after loading - Check row counts and sample data
  6. Clean staging directory - Remove copied SSTables after successful load
  7. Consider repair - Run repair after large data loads for consistency

Cautions

  • Does not create keyspace or table schemas
  • Source files are not deleted after loading
  • Large loads can impact cluster performance
  • Authentication credentials in command line may be visible in process lists

CommandRelationship
nodetool snapshotCreate snapshots for loading
nodetool refreshAlternative for loading local SSTables
nodetool importImport SSTables from directory
nodetool netstatsMonitor streaming progress
sstableutilList SSTable files