Schedule icon
Webhook icon
Assert icon
Request icon
Script icon
Set icon
If icon
SlackIncomingWebhook icon
Pause icon
Loop icon
Sleep icon
Fail icon
Log icon

Detect and Resume Stuck Paused NSQ Channels with Accumulating Backlog

Detect NSQ channels stuck paused with a growing backlog, track trend in KV, and unpause with operator approval and verification in Kestra.

Categories
DataInfrastructure

NSQ lets an operator pause a channel to stop message delivery during a deploy, an incident, or while debugging a misbehaving consumer. Pausing is a deliberate, manual action via the /channel/pause HTTP endpoint, and unpausing is just as manual via /channel/unpause. There is no timeout and no automatic resume: a channel paused during a 2am incident and never explicitly unpaused stays paused indefinitely, silently accumulating a backlog that produces no consumer errors, no failed deliveries, nothing but a quietly growing depth on a channel nobody is looking at anymore.

This blueprint provides an automated guard that fetches channel statistics from nsqd's HTTP stats API, flags channels that are paused AND accumulating a real backlog (an intentionally paused, empty channel is left alone), correlates against historical snapshots in Kestra KV to require the condition persist across multiple audit passes before treating it as stuck, requests human approval, calls the nsqd unpause endpoint, and re-verifies the channel actually resumed. It also surfaces (without ever attempting to auto-fix) channels that are not paused but show a high requeue/timeout ratio, since that usually means a consumer process is unhealthy and nsqd's admin API has no safe way to restart an external consumer.

How it works

  1. Pre-flight Assertion: validate_inputs (io.kestra.plugin.core.execution.Assert) checks threshold ordering and bounds before calling nsqd.
  2. Stats Collection: fetch_nsqd_stats (io.kestra.plugin.core.http.Request) calls GET /stats?format=json on the nsqd HTTP API, returning every topic's channels with paused, depth, in_flight_count, requeue_count, and timeout_count.
  3. Triage: triage_channels (io.kestra.plugin.scripts.python.Script) classifies each channel: paused with backlog at or above critical_backlog_depth escalates immediately; paused with a smaller backlog persisting for min_consecutive_paused_runs consecutive audits (tracked via Kestra KV under inputs.cursor_key) escalates as stuck; a paused-but-empty channel is left alone as presumed-intentional; a non-paused channel with a high requeue/timeout ratio is recorded as a diagnostic-only signal.
  4. State Persistence: save_tracker_kv (io.kestra.plugin.core.kv.Set) writes the updated per-channel pause trend back to Kestra KV.
  5. Slack Triage Alert: When stuck-paused channels exist, dispatch_slack_alert posts affected channels, backlog depth, and escalation reason, plus any diagnostic-only failing-consumer signals.
  6. Human Approval Gate: When auto_remediate is enabled and dry_run is false, pause_for_operator_approval (io.kestra.plugin.core.flow.Pause) halts execution until an operator resumes with approved: true.
  7. Unpause and Verify: remediate_stuck_channels (io.kestra.plugin.core.flow.Loop) calls POST /channel/unpause per approved channel, waits briefly, re-queries stats for that channel, and fails loudly via io.kestra.plugin.core.execution.Fail if it is still reported as paused.
  8. Resolution Notification: A confirmation card is posted to Slack once remediation completes, and the full audit manifest is archived in Kestra KV.
  9. Failure Handling: A flow-level errors block alerts Slack if nsqd connectivity or scripting fails unexpectedly.

What you get

  • Automated detection of channels paused during an incident and forgotten, before their backlog grows unbounded.
  • A safe-by-design heuristic that never touches an intentionally paused, empty channel.
  • Historical trend tracking in Kestra KV to require persistence across runs before treating a pause as stuck.
  • Human-in-the-loop approval before any unpause call touches live channel state.
  • Post-remediation verification that fails loudly instead of assuming the unpause worked.
  • Visibility into failing-consumer channels without falsely claiming an automated fix that doesn't exist.

Who it's for

  • Platform Engineers and SREs operating NSQ clusters for event or job distribution.
  • Backend Engineers who own NSQ consumers and need to know when a channel was paused and left that way.
  • Incident responders cleaning up after a deploy or outage where a channel was paused as a mitigation step.

Why orchestrate this with Kestra

NSQ itself has no concept of "this channel has been paused too long" and no built-in alerting on pause state. A cron job calling unpause blindly on every paused channel it finds would also resume channels an operator is still intentionally debugging. Kestra adds declarative scheduling, KV-backed trend state so a pause has to persist before it is acted on, an interactive approval gate, and verified, auditable remediation on top of the raw nsqd API.

Prerequisites

  • A reachable nsqd instance (NSQ 1.0 or higher) with its HTTP port (default 4151) reachable from the Kestra worker.
  • Network-level access control on that port: nsqd's HTTP API has no built-in authentication, so restrict access via VPN, firewall, or a reverse proxy in front of it.
  • A Slack Incoming Webhook URL for triage and resolution notifications.

Secrets

  • SLACK_WEBHOOK_URL: Slack Incoming Webhook endpoint for triage and resolution alerts.
  • NSQ_GUARD_WEBHOOK_KEY: Secret authentication token protecting the on-demand webhook trigger.

Quick start

  1. Configure SLACK_WEBHOOK_URL and NSQ_GUARD_WEBHOOK_KEY in your Kestra namespace secrets.
  2. Import this blueprint and set nsqd_url to your nsqd instance's HTTP endpoint.
  3. Run a manual execution with the default dry_run: true to audit current channel pause state without mutating anything.
  4. Review the execution logs, Slack triage card, and the KV entry under inputs.cursor_key.
  5. Run with auto_remediate: true and dry_run: false to arm remediation; when stuck-paused channels are detected, approve the pause_for_operator_approval task with approved: true and observe the verified unpause.
  6. Enable the periodic_pause_audit schedule trigger for continuous monitoring.

How to extend

  • Per-Channel Allowlist: Add an exempt_channels input so long-lived, intentionally paused archival or debug channels never show up in triage at all.
  • Empty-and-Purge Path: For channels confirmed to be holding unrecoverable messages (bad schema, deleted downstream target) rather than a backlog to replay, add a branch calling POST /channel/empty instead of unpause.
  • PagerDuty Escalation: Add io.kestra.plugin.pagerduty.PagerDutyAlert when overall_status is CRITICAL to page the on-call engineer directly.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.