This is a list of the public Cloudflare bill spikes I found in 2026 threads on Cloudflare Community and Hacker News. Seven of the eight are D1 rows read. One is a Durable Objects alarm loop.
In every case the fix was one index or one guard on the re-schedule. The hard part was never the fix. It was that nobody saw the meter move for days.
Rules for the table: public thread title, date, product and amount only. No usernames, no quoted text, no links to the threads. Amounts are what the poster stated, rounded; where none was given, it says so.
Last checked 2026-09-15. I add rows as I find them; the updated date at the top moves when I do.
The 8 incidents, by product and amount
| Date | Source | Product | Amount | What moved |
|---|---|---|---|---|
| 04-16 | HN | Durable Objects | about $34,895 over 8 days | Alarm re-scheduled itself in a loop; zero users |
| 06-29 | CF Community | D1 | about $800 | Sitemap of 380,000 pages crawled; every page a full-table read |
| 08-03 | CF Community | D1 | about $176 | Rows read overage on a small site |
| 08-10 | CF Community | D1 | about $4,115 | $5 subscription; D1 rows read ran for a month |
| 08-25 | CF Community | Workers / D1 | not stated | "Accidentally incurred a large billable usage" |
| 09-01 | CF Community | D1 | invoice about $1,481, credit asked about $976 | 1.476 trillion rows read |
| 09-03 | CF Community | D1 | not stated | Overage after a data migration; backfill loop |
| 09-11 | CF Community | D1 | quota hit, no invoice yet | Rows read shown as 235k in one view and 11.5M in another |
Eight rows. Seven are D1, one is Durable Objects. The smallest stated amount is $176, the largest $34,895.
For reference, D1 pricing is $0.001 per million rows read. The 09-01 invoice is simply what 1.476 trillion of anything costs on a per-million meter.
Why does D1 bill rows read instead of requests?
D1 meters rows scanned, not queries. A SELECT ... WHERE slug = ? on a table with no index on slug scans the whole table on every request. 10,000 rows, 100 requests a minute, one day: 1.4 billion rows for one small site. Query count never moves; the rows_read meter does.
Every D1 case in the table is that meter. The 09-03 migration case is the same thing in a different shape: a backfill that ran SELECT inside a loop over a table that had just grown.
Durable Objects alarm loops that never sleep
The Durable Objects case is an alarm handler that set the next alarm at the end of every run, including runs that failed.
Durable Objects requests are metered per million on Workers Paid. A loop with no sleep and no owner runs until the invoice arrives. Eight days, about $34,895, zero users.
A 10,000x jump that nobody saw for days
None of these are Cloudflare being expensive. In every thread the metric jumped 10,000x or more, and the first notification was the invoice or a quota email.
Cloudflare's Budget alerts (introduced 2026-04, default-on since 2026-07 for pay-as-you-go accounts) send a single email at the threshold. The docs call them informational only: they do not pause or cap usage, and the account owner still has to log in and act.
Where to see D1 rows read and DO requests before the invoice
- Dashboard: Workers & Pages → D1 → your database → Metrics. "Rows read" is per database, per day. A straight line that suddenly is not: that is it.
- GraphQL Analytics: dataset
d1AnalyticsAdaptiveGroups, dimensiondatabaseId, sum ofreadQueriesandrowsReadover a date range. Same numbers as the dashboard, scriptable. - Durable Objects: Workers & Pages → Durable Objects → Metrics. Requests and alarm invocations per namespace. One namespace climbing on a flat account is the loop.
The question worth automating is not "what is the total". It is "is today more than 10x the last seven days".
How I now guard my own D1 and Durable Objects usage
- Every D1 table I query by a non-primary-key column has an index on that column. New queries go through
EXPLAIN QUERY PLANfirst; anything that saysSCANgets an index or gets rewritten. My own D1 is about 15,000 rows, so this is prevention, not a war story. - I do not run Durable Objects yet. When I do, the re-schedule goes in the success path only, with a retry counter on the object.
- The "10x the last seven days" check runs on my own account since 2026-09-15 as a small read-only Worker, usage-guard-collector (MIT). It reads the GraphQL Analytics API every 6 hours into a D1 table and flags a meter when today is 10x its 7-day median. The hosted version linked below is still a waitlist page.
Limits of this page: eight rows is not a dataset, the amounts are self-reported, and I only read English-language threads. If you know of a public thread that belongs here, the address in the footer works.