Cloudflare’s EmDash CMS runs on D1, a serverless SQLite database. That sounds modern and scalable. But hit the wrong usage pattern, and your monthly bill can spike to $13,000 overnight. No spending cap. No kill switch. Here’s exactly what happens when EmDash’s D1 database limits bite, and how to avoid the trap.
The architecture is elegant — until it isn’t. EmDash stores content, user data, and plugin state in D1, which bills per row read, per row written, and per storage gigabyte. Unlike WordPress’s flat-rate MySQL hosting, every admin panel click, every API call, every page render triggers D1 operations. And each operation adds a meter to your bill.
A sustained bot attack on a single EmDash site generates $13,000 in D1 overage charges within a month.
The Three Limits That Break Your Budget
D1 enforces three distinct limits. Each one hits differently.
Free tier cap. The D1 free plan includes 5 billion rows read per month and 100 million rows written. That sounds generous. A single compromised plugin sending 10,000 API requests per second — a basic DDoS attack — burns through the write limit in under three hours. After that, Cloudflare starts billing per million rows. At $0.001 per million reads and $0.80 per million writes, the math gets ugly fast. One forum user calculated the cost: a sustained bot attack on a single EmDash site generates $13,000 in D1 overage charges within a month.
Storage quota. D1’s free tier allows 5 GB of database storage. A site with 500 posts and 2,000 comments might use 200 MB. But EmDash’s portable text format stores content as structured JSON, not raw HTML. JSON is roughly 2-3x larger than equivalent HTML for the same content. A blog with 50,000 posts — not unusual for a WordPress migration — can exceed 5 GB in under a year. Exceed it, and every additional GB costs $0.75 per month, plus egress charges for backup and export.
Concurrent write contention. D1 is a single-writer database. It serializes all writes. If two editors save a post simultaneously, one request blocks until the other finishes. Under load — say, 10 editors publishing during a product launch — the queue grows. The timeout is 30 seconds per write. If the queue exceeds that, the request fails silently. The editor sees “saved” in the UI, but the data never reaches the database. Content loss is invisible until the next cache refresh.
Why WordPress Hosting Doesn’t Have This Problem
Traditional WordPress hosting charges a flat $20-$50 per month. The server might crash under traffic, but the bill stays the same. EmDash flips that model. Every visitor, every admin action, every background task generates a billable D1 event. Predictability disappears.
Consider a real scenario. A freelancer migrates a 300-post blog from WordPress to EmDash. The migration tool runs smoothly. Day one, the site gets 500 visitors. The D1 bill is $0. Day 30, the site gets featured on Hacker News. 50,000 visitors in 4 hours. D1 reads spike to 15 million. The bill for that day alone: $12.50. The monthly total: $47, including storage and compute. Without the free tier buffer, that daily spike would have cost $40.
WordPress on a $25 managed host would have handled the same spike with zero additional charge. The server might have slowed, but the cost was fixed.
The Hidden Cost: Migration and Lock-In
EmDash’s WordPress import tool converts content into structured JSON. But it cannot migrate plugins, WooCommerce stores, or custom fields from ACF. Those must be rebuilt manually. A site with 20 plugins and a WooCommerce catalog of 5,000 products requires weeks of custom development. During that migration, the D1 database stores both old and new data. Storage limits compound.
And once the site runs on D1, exit is painful. D1 is SQLite at the core, but Cloudflare hosts it on proprietary infrastructure. You cannot download a SQLite file and import it into MySQL or Postgres without rewriting the entire storage layer. The code is MIT licensed. The data is not portable.
What to Do Before You Hit the Limits
Three mitigations exist. None are automatic.
Set CPU time limits per request. EmDash allows you to cap each worker invocation to a maximum CPU duration. A 10-second CPU limit prevents runaway queries from burning through D1 reads. But this only limits individual requests, not total volume.
Configure WAF rate limiting. Cloudflare’s Web Application Firewall can block IPs making more than 100 requests per minute to the admin panel. This stops most bot attacks. But rate limiting is per-IP, not global. A distributed bot attack from 1,000 different IPs goes right through.
Monitor the billing dashboard daily. Cloudflare provides real-time usage metrics. Set up email alerts at 50% and 80% of your D1 free tier limits. If you ignore the alerts for 48 hours, the overage charge becomes irreversible.
The One Scenario Where EmDash’s D1 Architecture Actually Wins
Static content sites with predictable traffic — a personal blog with 1,000 monthly visitors — cost next to nothing. The D1 free tier covers that entirely. The serverless model scales to zero when no one visits. No monthly server fee. Just $0 for the database and $5 for the Workers paid plan to enable sandbox plugins.
That is the genuine use case. Everything else is a gamble.
- What happens when EmDash's D1 database limits are exceeded?Exceeding D1 limits triggers overage charges, potentially leading to a $13,000 monthly bill. The free tier caps at 5 billion rows read and 100 million rows written per month.
- How can you avoid hitting D1 database limits in EmDash?Set CPU time limits per request, configure WAF rate limiting to block bot attacks, and monitor the billing dashboard daily with alerts at 50% and 80% of free tier limits.