Sidekiq Job Monitoring with DeadManCheck
Sidekiq tells you when a job raises an exception. It doesn't tell you when a job runs,
processes zero records, and exits cleanly. DeadManCheck does.
What Sidekiq's built-in monitoring misses
Sidekiq's retry mechanism and dead queue handle raised exceptions well. But the failures
that go unnoticed aren't exceptions — they're silent successes: jobs that complete with
no error and no useful output.
- Nightly export processes 0 rows — upstream query returns empty. Job exits cleanly, Sidekiq marks it done.
- Scheduled job stops running — sidekiq-cron schedule gets accidentally cleared. No alert fires.
- Worker takes 10× longer than usual — data volume spike or slow database. Sidekiq doesn't alert on duration anomalies.
- Sidekiq process dies — dyno restart, OOM kill, or deploy issue. Jobs queue up. Nobody notices until users complain.
The dead man's switch pattern fixes this: your job pings an external service on success,
and that service alerts you if it stops hearing from the job on schedule.
Add monitoring to any Sidekiq worker
Add start, success, and fail pings to your worker's perform method.
Uses Ruby's stdlib Net::HTTP — no extra gem required.
# app/workers/daily_export_worker.rb
require 'net/http'
require 'json'
class DailyExportWorker
include Sidekiq::Job
TOKEN = ENV['DEADMANCHECK_TOKEN']
BASE = "https://deadmancheck.io/ping/#{TOKEN}"
def perform
dmc_start
rows = run_export
dmc_success(rows)
rescue
dmc_fail
raise # re-raise so Sidekiq handles retries
end
private
def dmc_start
Net::HTTP.get(URI("#{BASE}/start"))
rescue; end
def dmc_success(count)
uri = URI(BASE)
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
req.body = { count: count }.to_json
Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
rescue; end
def dmc_fail
Net::HTTP.get(URI("#{BASE}/fail"))
rescue; end
end
Set the monitor interval slightly longer than your schedule — e.g.
25 hours for a daily job.
DeadManCheck alerts if the success ping doesn't arrive within that window.
Using sidekiq-cron or sidekiq-scheduler?
The same worker pattern applies. If you're using
sidekiq-cron or
sidekiq-scheduler
to run jobs on a schedule, your perform
method is already the right place to add the pings — no extra configuration needed.
# config/schedule.yml (sidekiq-scheduler)
daily_export:
cron: "0 2 * * *"
class: DailyExportWorker
queue: default
# The worker above handles all pings — nothing else to configure.
One monitor per scheduled job. If sidekiq-cron loses its Redis state after a restart,
DeadManCheck will alert you — the expected ping never arrives.
Output assertions: catch workers that do nothing
DeadManCheck's output assertion feature alerts you
when a job completes but the count it reports is below a threshold you set.
Cronitor, Healthchecks.io, and Better Stack don't have this — they only check that the
ping arrived.
- Export worker exported 0 rows → alert (even though the job succeeded)
- Billing sync processed 0 invoices → alert
- Notification worker sent 0 emails → alert
Pass the count in the POST body and configure your threshold in the monitor settings:
# POST to /ping/{token} with count — triggers assertion check
uri = URI("https://deadmancheck.io/ping/#{TOKEN}")
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
req.body = { count: rows_exported }.to_json
Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
See how output assertions work →
Duration monitoring for slow workers
DeadManCheck tracks how long each job run takes and alerts when a run takes significantly
longer than the rolling average. The start ping triggers the timer; the success ping stops it.
After 5+ runs, DeadManCheck builds a rolling baseline. A job that normally takes 30 seconds
but suddenly takes 8 minutes gets flagged — a leading indicator of a slow query, a data
volume spike, or a downstream service degrading.
Learn more about duration monitoring with rolling average anomaly detection →
Setup in 2 minutes
- Create a free monitor — set interval to match your job schedule + buffer
- Copy your monitor token into
DEADMANCHECK_TOKEN env var
- Add the
dmc_start / dmc_success / dmc_fail helpers to your worker
- Optionally configure an output assertion threshold in the monitor settings
- Deploy and watch the first ping arrive in the dashboard
Start monitoring free — no credit card needed
Free for 5 monitors. $12/mo for 100. Self-host for free.