Skip to content

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

nodetool tpstats

Prints the task counters for every thread pool the node registers, followed by the messages the node has dropped by message type.


Terminal window
nodetool [connection_options] tpstats [options]

See connection options for connection options.

nodetool tpstats reads the thread pool metrics the node registers over JMX and prints one row per pool, then a second section counting dropped messages by type. It reports the node it connects to, at the moment it runs. system_views.thread_pools returns the same pools over CQL; see thread_pools virtual table.

This page covers the command, its options and how to read its output. A pool name printed in that output can be looked up in Thread Pools, which records what each pool does and which of 5.0, 4.1 and 4.0 report it.


OptionDescription
-F, --formatOutput format (json, yaml)
-v, --verboseShow detailed thread pool sizes (core, max, active)

Pool Name Active Pending Completed Blocked All time blocked
ReadStage 2 0 1234567 0 0
MutationStage 4 3 9876543 0 0
CounterMutationStage 0 0 1234 0 0
GossipStage 0 0 567890 0 0
RequestResponseStage 0 0 8765432 0 0
AntiEntropyStage 0 0 123 0 0
MigrationStage 0 0 12 0 0
MiscStage 0 0 5678 0 0
CompactionExecutor 2 0 234567 0 0
MemtableFlushWriter 1 0 12345 0 0
MemtablePostFlush 0 0 12345 0 0
MemtableReclaimMemory 0 0 12345 0 0
PendingRangeCalculator 0 0 5 0 0
Sampler 0 0 0 0 0
SecondaryIndexManagement 0 0 50 0 0
HintsDispatcher 0 0 100 0 0
Native-Transport-Requests 8 12 12345678 0 0
ViewMutationStage 0 0 0 0 0
ViewBuildExecutor 0 0 0 0 0
Message type Dropped Latency waiting in queue (micros)
50% 75% 95% 98% 99% Max
READ 0 125.0 234.0 567.0 890.0 1234.0 5678.0
RANGE_SLICE 0 234.0 345.0 678.0 901.0 1345.0 6789.0
MUTATION 0 89.0 123.0 345.0 456.0 567.0 2345.0
READ_REPAIR 0 456.0 567.0 789.0 1012.0 1234.0 7890.0
COUNTER_MUTATION 0 123.0 234.0 456.0 567.0 678.0 3456.0
HINT 0 45.0 67.0 123.0 178.0 234.0 1234.0
REQUEST_RESPONSE 0 34.0 45.0 89.0 123.0 156.0 890.0

FieldDescription
Pool NameName of the thread pool
ActiveThreads currently executing tasks
PendingTasks waiting for a thread
CompletedTotal tasks completed
BlockedSubmissions waiting for queue space at the instant of the call. Zero on every pool on 5.0, 4.1 and 4.0
All time blockedSubmissions the pool held or refused since the node started. Only TracingStage, Sampler and Repair-Task under repair_command_pool_full_strategy: reject can move it, and only on 5.0 and 4.1
FieldDescription
Message typeType of inter-node message
DroppedMessages dropped due to timeout
Latency percentilesTime spent waiting in queue

Pool Name Active Pending Completed Blocked All time blocked
ReadStage 1 0 1234567 0 0
MutationStage 2 0 9876543 0 0
CompactionExecutor 1 3 234567 0 0

Active close to the pool size with Pending at zero is a busy pool rather than a problem, and a short queue on a background pool such as CompactionExecutor is expected. A Pending count that persists across successive runs means the pool is not keeping up with what is handed to it, and is the reading to act on. The Blocked and All time blocked columns are not the saturation signal they appear to be: on 5.0, 4.1 and 4.0 both stay at zero for ReadStage, MutationStage, Native-Transport-Requests and every compaction, validation and flush pool, since the blocking path was removed from the shared executor before 4.0 was released (CASSANDRA-16186). What the blocked counters report states the three pools that can move All time blocked on 5.0 and 4.1. The counters reset when the node restarts.

tpstats -v adds the core and maximum size of each pool, which gives the denominator for the Active column.

What a backlog on a particular pool indicates, and which settings size it, is covered per pool in Thread Pools.


The second section counts messages the node discarded rather than executed, by message type.

Message type Dropped
READ 125
MUTATION 50

A message is dropped when it has waited in a stage queue past the timeout of its verb, because the coordinator that sent it has already given up. Drops on READ and MUTATION are therefore the downstream symptom of the saturation that the pool section shows as pending tasks on ReadStage and MutationStage, and the two sections should be read together. Dropped mutations are recorded as hints and replayed later; dropped reads are not retried by the node. Thread Pools covers the consequences by verb.

What pushes a verb past its timeout differs by verb:

Message typeWhat causes drops
READSlow data devices, large partitions, garbage collection pauses
MUTATIONWrite overload, memtable flush pressure
READ_REPAIRSaturated or slow replicas, leaving the repair mutation unapplied within write_request_timeout
REQUEST_RESPONSENetwork latency, cross data centre round trips

Every verb the node counts, with the metric that carries it, is listed in AxonOps Dropped Messages Dashboard Metrics Mapping.

Terminal window
# Latency of the requests the coordinator did serve
nodetool proxyhistograms

Terminal window
nodetool tpstats
Terminal window
nodetool tpstats -F json
Terminal window
nodetool tpstats -v
Terminal window
watch -n 2 'nodetool tpstats | head -20'
Terminal window
nodetool tpstats | awk '$3 > 0 {print}'

Field 3 is the Pending column. The header row prints nothing, since awk compares its text as zero.

#!/bin/bash
# Compare thread pool stats across all nodes using SSH
for node in node1 node2 node3; do
echo "=== $node ==="
ssh "$node" "nodetool tpstats" | grep -E "ReadStage|MutationStage|Pending"
done

The pools are sized in cassandra.yaml, and the four request stages can be resized on a running node with nodetool setconcurrency. The setting behind each pool is listed in Thread Pools, which also covers when resizing is the wrong response to a backlog.


CommandRelationship
infoGeneral node information
proxyhistogramsRequest latency histograms
tablestatsTable-level statistics
compactionstatsActive compaction details
netstatsNetwork/streaming statistics
gcstatsGC statistics