Schedule icon
Script icon
If icon
SlackIncomingWebhook icon
Log icon
Return icon

Cassandra Hinted Handoff Storm Guard

Audits Apache Cassandra hinted handoff delivery queues during node recovery, calculating backlog pressure and alerting SREs on Slack.

Categories
DataInfrastructure

In distributed Apache Cassandra architectures, coordinators temporarily store write mutations as hints on local disk when a peer replica node becomes unreachable. When that recovering node rejoins the cluster, coordinators initiate replay sequences to flush accumulated hints.

During major network partitions or prolonged rolling node restarts, millions of pending hints build up across surviving coordinators. Once the recovering instance announces availability, all coordinators attempt simultaneous parallel hint replay, triggering a classic hinted handoff storm. This saturated flood exhausts coordinator JVM heap buffers, causes GC pauses, and chokes inter-datacenter network links.

This blueprint provides an automated cluster durability sentinel. Running on a recurrent ten-minute schedule, it monitors Cassandra StorageMetrics metrics via Prometheus/JMX endpoints, calculates total in-flight and pending handoffs against safety limits, and delivers proactive alerts to SRE teams before cascading node failures happen.

How it works

  1. Recurrent Pulse Trigger: The poll_cassandra_hints trigger (io.kestra.plugin.core.trigger.Schedule) initiates the metric scan every ten minutes.
  2. JMX and Prometheus Scrape: The scan_hinted_handoff_metrics task (io.kestra.plugin.scripts.python.Script) fetches coordinator metrics, aggregating total hints created, succeeded, timed out, and currently in flight.
  3. Threshold Gate: The evaluate_handoff_storm flowable task (io.kestra.plugin.core.flow.If) evaluates whether pending or in-flight hints exceed designated saturation thresholds.
  4. Slack Incident Alert: When handoff pressure exceeds configured limits, alert_slack_handoff_storm (io.kestra.plugin.slack.notifications.SlackIncomingWebhook) delivers an actionable notification with diagnostic commands (nodetool statushandoff, nodetool disablehandoff).
  5. Healthy Confirmation: When hint metrics indicate healthy flow, log_nominal_hint_flow logs cluster operational health.
  6. Manifest Export: The export_handoff_manifest task emits structured JSON telemetry for Datadog, Grafana, or operational dashboards.

Architecture diagram

flowchart TD
    A[Schedule: Every 10 Minutes] --> B[scan_hinted_handoff_metrics: Cassandra StorageMetrics]
    B --> C{Handoff Storm Detected?}
    C -- Yes --> D[alert_slack_handoff_storm: Slack Webhook]
    C -- No --> E[log_nominal_hint_flow: Log]
    D --> F[export_handoff_manifest: Return JSON]
    E --> F

Use cases

  • Post-Maintenance Cluster Recovery: Prevent coordinator node crashes when restarting nodes following rolling kernel or Cassandra minor version upgrades.
  • Multi-Datacenter WAN Protection: Safeguard limited inter-datacenter bandwidth from saturation caused by unthrottled hint replay streams.
  • Proactive Node Remediation: Alert database reliability engineers before JVM GC pauses lead to false gossip failure detector node expulsions.

Inputs

Name Type Default Description
jmx_exporter_url STRING "http://localhost:7070/metrics" Prometheus or JMX exporter endpoint exposing Cassandra StorageMetrics.
hinted_handoff_threshold INT 50000 Maximum pending hinted handoff mutations threshold before declaring a storm.
max_hints_in_flight INT 10000 Maximum allowable concurrent hints being dispatched to recovering nodes.
slack_channel STRING "#cassandra-reliability" Slack channel destination for distributed storage reliability notifications.

Expected outputs

  • {{ outputs.scan_hinted_handoff_metrics.vars.has_storm }}: Boolean flag indicating if a hinted handoff storm is active.
  • {{ outputs.scan_hinted_handoff_metrics.vars.pending_hints }}: Calculated backlog of pending hints waiting for delivery.
  • {{ outputs.scan_hinted_handoff_metrics.vars.in_flight_hints }}: Number of hints currently in flight to target replicas.
  • {{ outputs.scan_hinted_handoff_metrics.vars.hints_timed_out }}: Count of expired hints dropped past max_hint_window_in_ms.
  • {{ outputs.scan_hinted_handoff_metrics.outputFiles['cassandra_hint_report.json'] }}: Structured diagnostic JSON artifact.

Prerequisites

  • Cassandra cluster with Prometheus JMX exporter or Cassandra exporter enabled on port 7070.
  • Incoming Webhook URL configured in Slack for your database reliability channel.

Secrets

  • SLACK_WEBHOOK_URL: Slack Incoming Webhook endpoint URL with permissions to post messages.

Quick start

  1. Configure SLACK_WEBHOOK_URL in your Kestra namespace secrets.
  2. Import this flow YAML into your Kestra workspace.
  3. Update jmx_exporter_url with the network address of your Cassandra coordinator or Prometheus service.
  4. Execute the flow manually from the Kestra UI to verify metric ingestion and alert routing.

Common pitfalls and troubleshooting

  • Expired Hints Silently Dropped: By default, Cassandra drops hints older than three hours (max_hint_window_in_ms); monitor hints_timed_out to identify when full nodetool repair is required instead of relying on handoffs.
  • Prometheus Metric Path Formatting: Depending on exporter version, metrics may be prefixed with cassandra_storage_ or jvm_cassandra_storage_; ensure your scraper regex accommodates your specific exporter naming convention.

How to extend

  • Add automated dynamic throttling invoking nodetool sethintedhandoffthrottlekb via SSH or Ansible when handoff pressure surges.
  • Integrate with PagerDuty for high-priority on-call paging during critical multi-node failover scenarios.
  • Automatically trigger nodetool repair --in-dc on recovering nodes if hints_timed_out exceeds zero.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.