Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
YouTube Security VideosGoogle Chrome: Unfinished Projects: Solange’s Public Sculpture(21.09.2026 um 17:02 Uhr)
Windows Tipps & SecurityBlurry or pixelated video in Microsoft Teams(21.09.2026 um 14:34 Uhr)
Sicherheitslücken (CVE)USN-8791-1: Ghostscript vulnerability(21.09.2026 um 14:51 Uhr)
Sicherheitslücken (CVE)USN-8792-1: Memcached vulnerability(21.09.2026 um 15:02 Uhr)
Sichere ProgrammierungI stopped rewriting the same Electron boilerplate — so I packaged it(21.09.2026 um 17:28 Uhr)
YouTube Security VideosGoogle Chrome: Unfinished Projects: Solange’s Public Sculpture(21.09.2026 um 17:02 Uhr)
Windows Tipps & SecurityBlurry or pixelated video in Microsoft Teams(21.09.2026 um 14:34 Uhr)
Sicherheitslücken (CVE)USN-8791-1: Ghostscript vulnerability(21.09.2026 um 14:51 Uhr)
Sicherheitslücken (CVE)USN-8792-1: Memcached vulnerability(21.09.2026 um 15:02 Uhr)
Sichere ProgrammierungI stopped rewriting the same Electron boilerplate — so I packaged it(21.09.2026 um 17:28 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

What actually breaks when a free Cloudflare D1 database hits its 500 MB wall

Every "free serverless DB" comparison ranks capacity, price, and cold-start. Almost none answer the question you actually hit in production: what happens at the free-tier wall? So I filled a Cloudflare D1 database to its limit over the…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Every "free serverless DB" comparison ranks capacity, price, and cold-start. Almost none answer the question you actually hit in production: what happens at the free-tier wall? So I filled a Cloudflare D1 database to its limit over the REST API and poked it.



The honest short version: the wall is not a full read-only lockout, a plain DELETE clears it immediately (but that recovery is not quota-free), and — the part I got wrong twice — building an index on a blob column roughly doubles your storage, so it slams into the wall on its own. This post has been revised twice: my own size_after logs, and then a follow-up experiment, corrected me. I'll show both corrections instead of hiding them.



Scope: Workers Free, throwaway DBs, over the D1 REST API /query, 2026-07. The coarse wall was reproduced on a second, freshly-created database; the exact-ceiling pin and the index-doubling are each n=1 (flagged). This is a REST probe, not a Worker Binding probe — don't generalize endpoint-specific behavior (especially VACUUM).






"The free-tier wall" is not one wall



D1 has several walls, with different scopes and — per Cloudflare's own error list — different messages:






































Wall Scope Value (Free) Documented message
per-DB storage per database
500 MB (Paid: 10 GB)

Exceeded maximum DB size — action: "delete rows / shard"
account storage account 5 GB Your account has exceeded D1's maximum account storage limit…
daily rows read account 5,000,000/day daily-limit-exceeded → "can't run queries"
daily rows written account 100,000/day same (INSERT, UPDATE, and DELETE all count as writes)


(Free daily counters reset at 00:00 UTC; storage is not daily-reset. Max row 2 MB; 100 columns; 10 DBs/account. All confirmed against the D1 docs on 2026-07-09.) I measured the first one.






Result 1 — the wall is 500 MB (decimal); pinned to one row on one DB, reproduced coarsely on a second



Filling with bulk inserts stalls around ~499.9 MB. To pin it, I then looped single-row inserts at the wall:




… 24 single-row inserts succeed (size_after climbs)
25th: HTTP 400 [{"code":7500,"message":"Exceeded maximum DB size"}]
last successful size_after = 499,994,624 bytes (≈ 499.99 MB ≈ 476.83 MiB)






That ceiling — 499,994,624 — is 500,000,000 (decimal 500 MB) minus 5,376 bytes, enforced at SQLite's 4 KB page granularity (499,994,624 = 122,069 × 4096). I reproduced the coarse wall on a second, freshly-created DB: it stopped at the identical 499,884,032 and returned the same 7500. One caveat so you can hold me to my own logs: the redacted results/*.jsonl carry no account IDs, and served_by_colo is Anycast edge routing, not an account signal — so what's verifiable from the evidence is a second database, and the byte-exact 499,994,624 pin is from the single-row probe on one of them (n=1). The wall firing at all means these DBs are on Workers Free (Paid = 10 GB).






Result 2 — not read-only, but small writes aren't "exempt" either (measured)



My first draft claimed small writes slip past the wall while big ones don't. Wrong — and my own numbers show why. Those 24 single-row inserts above consumed only 499,994,624 − 499,884,032 = 110,592 bytes (~110 KB) of headroom before even a single-row insert was rejected. So:





  • Reads always pass — near-tautological for a storage cap; reads don't grow the DB.


  • Writes pass only while headroom remains. Small writes weren't bypassing the wall; they were filling the last sliver before it. Call it slack, not exemption. (One headroom-exhaustion sequence, but the 25th insert failing at zero headroom is a clean counterexample to "small writes are exempt" — one is enough.)






Result 3 — recovery is a plain DELETE, no upgrade (but it spends write quota)






DELETE WHERE k < 20000    19,998 rows; size_after 499.9 MB  243,884,032 (~244 MB) immediately; rows_written = 19,998
bulk INSERT (after delete) restored
VACUUM 7500 "cannot VACUUM from within a transaction: SQLITE_ERROR" (maybe REST-specific)






DELETE drops D1's reported size immediately and writes resume — no VACUUM, no plan upgrade (recovery class R1). Two honest qualifiers: (1) it isn't quota-free — D1 counts DELETE as a write (docs: "Write operations include INSERT, UPDATE, and DELETE"), so this one 19,998-row delete spent ~20% of the daily 100k budget, and the cost scales with row count, not bytes freed (this delete freed ~256 MB ≈ 12.8 KB/row; whether it's linear per chunk I didn't separately measure); (2) size_after is D1's reported size — the meter dropping doesn't prove the physical file shrank (cf. workerd#1618, local).






Result 4 — CREATE INDEX doubles your storage (the thing I got wrong twice)



At the wall, CREATE INDEX fails with out of memory: SQLITE_NOMEM. My first draft lumped that in as "large allocation blocked"; after review I "corrected" it to "that's a memory limit, independent of the storage wall." Both were wrong.



On a control DB at 300 MB — well below the 500 MB wall — CREATE INDEX failed not with SQLITE_NOMEM but with 7500 "Exceeded maximum DB size" (storage!). Below the wall, a storage error? I measured the mechanism directly — deleted the control to 80 MB and indexed:




CREATE INDEX ON bench(v) at 84,029,440 (80.1 MiB)  OK
size_after 84,029,440 167,923,712 = ×1.998 growth (measured once, at ~80 MB)






An index on a blob column carries a copy of the column's data as its keys, so it roughly doubles storage — inferred from this one growth point, not proven in general. If that ×2 holds at other sizes:




























storage before index after (~×2) result
80 MB 160 MB ✅ succeeds (under the wall)
300 MB ~600 MB Exceeded maximum DB size (over the 500 MB wall)
500 MB (at the wall) SQLITE_NOMEM (OOMs during the build)


So the index failure is storage-bound via the index's own footprint, not "memory, unrelated to the wall." A rough rule of thumb — if the ×2 holds — is that on D1 Free you can only index a column holding up to ~250 MB of data (2 × 250 = 500 MB), but that's an extrapolation, not measured near 250 MB. The SQLITE_NOMEM is just what you see when you're already at the wall.






The error code, and what I did not measure



Cloudflare's error list classifies these by message (Exceeded maximum DB size, …account storage limit…, …isolate memory limit…); the number 7500 appears nowhere in the docs. So 7500 is a generic REST wrapper — the message is the discriminator.



Not measured / n=1 / extrapolated (so not claimed): the index ×2 is a single measurement at one size/row-shape; the ~250 MB threshold is extrapolated (not measured near 250 MB); DELETE linearity across chunks is not measured (one 19,998-row delete); the account 5 GB wall, the daily read wall (5M/day — reads stop, account-scoped), and Worker Binding behavior are all untested; size_after behaves like a coherent logical meter (dropped on the one DELETE, ~doubled on the one index build) but the docs don't say physical vs logical. One full cycle (fill 39k + recover 20k + control 24k ≈ 84k rows_written) fits in one UTC day but not two.






Reproduce it






git clone https://github.com/axiom-pro/free-tier-quota-probe
cd free-tier-quota-probe
npm install && npm run selftest
# .env: CF_ACCOUNT_ID / CF_API_TOKEN (D1:Edit) / D1_DATABASE_ID / D1_CONTROL_DATABASE_ID / BILLING_SAFE=confirmed
node --env-file=.env bin/d1-admin.mjs create wallprobe # create the DB via API (no dashboard needed)
npm run ping -- --target d1
npm run fill -- --target d1 --confirm-destructive
npm run probe-slack -- --target d1 # pins the wall + measures the headroom
npm run fill -- --target d1 --control --cap-mb 300 --confirm-destructive
npm run probe-index -- --target d1 # the index-doubling test






Node ≥ 20, ESM, D1 over native fetch (60 s timeout + one retry). Redacted captures are frozen in results/*.jsonl; predictions (and the follow-up amendment) are in PREREGISTRATION.md. Repo: https://github.com/axiom-pro/free-tier-quota-probe






I write about measurement discipline — filling the wall instead of quoting the limit, and correcting my own assumptions on the record. This post's Results 2 and 4 are the live examples: I reasoned wrong twice and only the measurements got it right. Written with AI assistance; every number is from the captured `results/.jsonl`, and the doc facts were re-verified against Cloudflare's D1 docs on 2026-07-09. A Japanese version of this write-up also exists.*

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten What actually breaks when a free Cloudflare D1 database hits its 500 MB wall

Thematisch verwandte Begriffe: What, actually, breaks, when · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-94393 | When a user creates or edits a report inside an event, MISP can identify…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick