queue-retry-storm
A queue's messages are retried 0.25 times or more each on average, or a consumer allows over 10 retries with no dead letter queue.
Fix: Ack messages one by one, set retry_delay, keep max_retries low and add a dead_letter_queue.
How to run it, what each rule checks, and what it can't see.
Try it on sample data first:
Create a read-only API token in your Cloudflare dashboard with Account Analytics Read,Workers Read, Queues Read and D1 Read, then:
--account <id>: which account to scan, or set CLOUDFLARE_ACCOUNT_ID--days <n>: whole UTC days of usage to read, 1 to 31 (default 3)--json: print the report as JSONUsage in the window is scaled to a 30-day month, included usage comes off, and Cloudflare's list prices apply. It's an estimate of a month like the one scanned, not an invoice.
Every report ends with a list of what couldn't be measured for your account. A rule that sees nothing can't tell "none" from "unknown", so read that list too.
With Guard Solo, a queue that goes over its own daily budget can be paused automatically. Delivery stops until you resume it: messages wait in the queue for its retention period (4 days by default), and producers can still send, which is billed. The pause happens in your account, through a small Worker you deploy: theBrake Worker. It holds a token that can edit your queues; Guard never does.
BRAKE_SECRET.When that queue passes its budget, Guard asks the Brake Worker to pause it and emails you. Resume it from the dashboard, or in Cloudflare. A queue you resume isn't paused again until the next UTC day. A paused queue doesn't resume by itself the next day. The Brake Worker only acts on a request signed with your secret, less than two minutes old and never seen before, for a queue on its list.
A high cost alone is never a finding. It only raises the severity of a real signal.
A queue's messages are retried 0.25 times or more each on average, or a consumer allows over 10 retries with no dead letter queue.
Fix: Ack messages one by one, set retry_delay, keep max_retries low and add a dead_letter_queue.
CPU per run doubled across the window, one run uses half of the 15-minute CPU limit, or a cron runs every 5 minutes or more often with over a second of CPU.
Fix: Process a bounded batch per run with a saved cursor.
A statement reads at least 1,000 rows per run, and at least 100 rows for every row it returns or writes.
Fix: Add an index on the columns in its WHERE clause, then check EXPLAIN QUERY PLAN.
A database holds data. The scanner can't see copies kept elsewhere, so it lists every database as a reminder.
Fix: Export on a schedule to storage you control, and test a restore.
Alarms fire at 1 a second or more, or one object re-arms more often than every 10 seconds. Cloudflare's analytics don't report alarms separately, so this rule can't fire on real accounts yet.
Fix: Only call setAlarm() when there is more work, with a minimum delay.