The system
How the system worksThe DirectoryDispatchThe LedgerAI modelsAI agentsYour installationThe appThe research libraryWhat changes for your businessUse it from your softwareEverything it can do
Messaging
iMessageWhatsApp
Ads and leads
AdsCreativeLeads
Devices
Devices
Industries
RealtorsRestaurantsHome services
Explore
How it worksPermissions and limitsCompareSet upQuestionsText me

The Cloudflare OS: one account running an entire build

A complete map of one production Cloudflare application: every binding, the billable unit, the $5 baseline, and the failure that produced a $34,895 invoice.

One Cloudflare account runs this application end to end: the pages, the API, the relational database, the append-only event store, the object store, the queue, the scheduled jobs, the headless browser, the model calls and outbound mail. No second host, no virtual machine, no container.

A binding is a line in a Cloudflare configuration file that attaches a resource to code and names the property the code reaches it by. env.DB is a binding. The resource behind it has an account-scoped identifier; the running code never sees that identifier, only the name. That indirection is why a preview deployment can point at a different database without one line of code changing.

Below: the complete binding list read out of the configuration files, the unit each one bills on, the arithmetic for a stated month, the failure that turns a hobby account into a five-figure invoice, and reports from people who ran this stack and stayed or left.

Evidence status

Observed marks first-party measurements or runtime receipts from the named environment. Derived marks arithmetic calculated from cited inputs. Specified marks vendor or standards documentation. Implemented and deployed name code and live-state evidence, respectively. Reproduced means the stated procedure was rerun. Externally attested marks operator reports; those reports show that an experience occurred, not that it is universal.

Nine bindings ship with the request layer

wrangler.toml at the repository root declares everything the page-and-API layer can touch. The account identifier and the workers.dev subdomain are redacted; nothing else is.

BindingKindWhat is behind itWhy this and not something else
DBD1 database loop-content-spine91 tables: articles, the capability directory, agents, leads, tasks, sessionsRelational reads with joins and indexes. KV cannot filter; R2 cannot query
LEDGERD1 database loop-shared-events12 tables, append-only: events, invocations, capabilities, hash-chain checkpointsSeparate database so a write-heavy audit trail cannot compete with page reads for the same storage limit
KVWorkers KV namespace loop_content_kv19 keys: OAuth handles, prompt settings, one cached audio blobConfig distributed to every location. Read-mostly, tolerant of eventual consistency
R2R2 bucket miscsubjects-ledger645 objects, 12.3 MB: vendored docs, disclosure receipts, agent-turn archivesBytes with no query on them. R2 charges nothing for egress; a database charges per row scanned
AIWorkers AIModel inference invoked from a requestInference without an outbound API key in the request path
DIRECTORY_DODurable Object class DirectoryDO in Worker loop-safe-directory-doSlug registry plus an append-only mutation-intent logSingle strongly-consistent writer. D1 cannot hold a transaction across two requests, so the serialization point has to be an object
TASKSQueue producer for loop-tasksWork handed off so the reader is not kept waitingA request has a wall-clock budget; a queue consumer has its own
STOREService binding to Worker loop-safe-storageBulk blobs in a second R2 bucket plus a D1 index over themKeeps a second bucket and a second database out of the Pages project's binding list. Worker-to-worker, no public route
META_BRIDGEService binding to Worker loop-meta-bridgeThe Meta Graph API, frontedThat Worker binds the Meta token by reference from Secrets Store. Nothing copies the token

All nine are repeated under [[env.preview.*]] in the same file, with DB and LEDGER pointing at loop-content-spine-preview and loop-shared-events-preview. Pages environment overrides do not inherit: a binding declared once at the top level and not repeated under env.preview does not exist in a preview deployment at all. Two D1 identifiers differ; the other seven bindings are byte-identical repetitions. That duplication is the only thing stopping a pull-request preview from writing to production data.

Seven more Workers hold what a request cannot

The Pages project is one deployment. Six sibling Workers carry the bindings a request-scoped runtime cannot own — scheduled execution, long jobs, durable state and mail — plus one that exists only to serve a single path.

WorkerBindings it ownsWhat it is for
loop-safe-siblingAI, DB, KV, R2, DO classes ExpertDO and AgentDO, Workflows DELIVER_WF and SELFTEST_WF, browser MYBROWSER, queue producer and consumer for loop-tasks, send_email binding EMAIL, cron /1 and 0 4 Everything on a clock, everything that survives a restart, everything that drives a browser
loop-safe-directory-doDB, DO class DirectoryDO, SQLite migration v1The one strongly-consistent writer for slugs
loop-safe-storageR2 bucket miscsubjects-store, D1 loop-storage-indexBulk blobs with a queryable index. workers_dev = false, reachable only via STORE
loop-meta-bridgeSecrets Store refs META_ACCESS_TOKEN, META_BUSINESS_ID, META_API_VERSIONMeta Graph reads only. workers_dev = false
miscsubjects-mcpDB, KV, DO class MiscsubjectsMCPModel Context Protocol server
oip-peerKV namespace oip-peer-storeA second federation node on a second registrable domain
miscsubjects-robotsRoute miscsubjects.com/robots.txtOne path, one Worker

DIRECTORY_DO and STORE are ordering traps: each names another Worker by script_name or service, and if that Worker has never been deployed the next Pages deploy fails on the binding, not at the call site. The target has to exist before the pointer does.

Secrets appear as names in code and as values nowhere in the repository

Sixty-eight uppercase environment names are referenced across the Functions code, of which 43 are credentials. They are Pages environment variables and Secrets Store references, never files in the repository. Regenerate the list:

shell
grep -rhoE 'env\.[A-Z][A-Z0-9_]{3,}' functions --include='*.js' | sed 's/env\.//' | sort -u
Line 1, Column 1Shell Script

Names only, values nowhere: ADMIN_SESSION_SECRET, AIG_TOKEN, AIG_RUN_TOKEN, AIG_SHIM_TOKEN, ANTHROPIC_API_KEY, ARCADS_API_KEY, BLOOIO_API_KEY, CF_API_TOKEN, CLOUDFLARE_API_TOKEN, CLOUDFLARE_GLOBAL_KEY, GEMINI_API_KEY, GITHUB_TOKEN, GROK_API_KEY, KIMI_API_KEY, MCP_TOKEN, META_ACCESS_TOKEN, MOONSHOT_API_KEY, OPENAI_API_KEY, STORE_KEY, STRIPE_SECRET_KEY, TELEGRAM_BOT_TOKEN, TERMINAL_KEY, VAULT_UNLOCK_TOKEN, X_API_KEY, X_ACCESS_TOKEN, and eighteen more of the same shape.

The comment in wrangler.toml records why these are plain Pages variables and not Secrets Store entries: wrangler 4.99 rejects [[secrets_store_secrets]] for a Pages project. The Meta bridge, which is a Worker and not Pages, does use Secrets Store — three references, store_id in the config, values never copied.

Every binding bills on a different unit, and only three of them can run away

The Workers Paid plan is $5.00 a month minimum for the account, and that subscription covers Workers, Pages Functions, KV, Hyperdrive and Durable Objects usage up to the included amounts below. Rates as published on 2026-07-26.

Binding kindThe unit that billsFree planPaid plan
Workers / Pages Functions requestsone request, cache hits included100,000/day10M/month, then $0.30/M
Workers CPU timeCPU milliseconds burned, not wall clock10 ms/invocation30M CPU-ms/month, then $0.02/M
D1 rows readrows a query scans, not rows it returns5M/day25 billion/month, then $0.001/M
D1 rows writtenrows changed, plus one per index touched100,000/day50M/month, then $1.00/M
D1 storageGB summed across every database on the account5 GB total5 GB, then $0.75/GB-month
KV readsone key, including reads that return null100,000/day10M/month, then $0.50/M
KV writes / deletes / listsone key, or one list call1,000/day each1M/month each, then $5.00/M
KV storageGB stored1 GB1 GB, then $0.50/GB-month
R2 storageGB-month, standard class10 GB-month/month$0.015/GB-month
R2 Class A operationswrites and listings1M/month$4.50/M
R2 Class B operationsreads10M/month$0.36/M
R2 egressbytes to the internetfreefree
Durable Object requestsHTTP, RPC sessions, WebSocket messages and alarm invocations100,000/day1M/month, then $0.15/M
Durable Object durationgigabyte-seconds the object is resident13,000 GB-s/day400,000 GB-s/month, then $12.50/M GB-s
Durable Object SQLite rowssame counters and rates as D15M read / 100,000 written per day25 billion read / 50M written per month
Queuesone operation; write + read + delete is three10,000/day1M/month, then $0.40/M
Workflows stepsone persisted step3,000/day500,000/month, then $0.80 per extra 100,000
Browserbrowser-hours, plus concurrent browsers averaged monthly10 minutes/day10 hours/month then $0.09/hour; 10 concurrent then $2.00/browser
Email sendingoutbound transactional mailnot availableincluded with Workers Paid; sending to verified destination addresses is free on all plans

Three of those units are unbounded by traffic and therefore the ones to watch. Durable Object requests count alarm invocations, so a self-scheduling object bills whether or not anyone visits. D1 rows read counts a scan, so one missing index multiplies the bill by the size of the table. Queue operations count three per message, so a retry storm triples on a metric that is already tripled.

One index turns 2,186 rows read into 1

The same lookup, run against the live production database twice on 2026-07-26, once through the slug index and once as a scan:

shell
npx wrangler d1 execute loop-content-spine --remote --json \
  --command "SELECT slug FROM articles WHERE slug='cloudflare-os'"
# "rows_read": 1, "duration": 0.1746

npx wrangler d1 execute loop-content-spine --remote --json \
  --command "SELECT slug FROM articles WHERE body LIKE '%DIRECTORY_DO%' LIMIT 5"
# "rows_read": 2186, "duration": 23.1205
Line 7, Column 1Shell Script

Same table, same result column, 2,186 times the billable work and 132 times the latency. LIMIT 5 does not help, because the limit applies to rows returned and the meter counts rows scanned. Every D1 query returns a meta object carrying rows_read and rows_written; that object, not the dashboard, is the cheapest place to catch a query that scans a table.

The arithmetic for one month at one million page views

Assume one million requests a month against this application, four D1 queries per page render, all of them indexed lookups that read fewer than fifty rows each, one KV read per render for the settings blob, and the storage measured above.

text
Workers Paid subscription                                        $5.00
Requests   1,000,000  (10,000,000 included)                      $0.00
CPU time   1,000,000 x 7 ms = 7,000,000 CPU-ms
           (30,000,000 included)                                 $0.00
D1 rows read   1,000,000 x 4 queries x 50 rows = 200,000,000
           (25,000,000,000 included)                             $0.00
D1 storage 281,989,120 + 1,061,666,816 bytes = 1.34 GB
           (5 GB included)                                       $0.00
KV reads   1,000,000  (10,000,000 included)                      $0.00
R2 storage 12,261,706 bytes = 0.0123 GB  (10 GB-month included)  $0.00
Queues     assume 20,000 messages x 3 operations = 60,000
           (1,000,000 included)                                  $0.00
                                                          ------------
TOTAL                                                            $5.00
Line 14, Column 1Plain Text

The included allowances are the point. At a million page views a month this application costs the subscription and nothing else. The same page views on the unindexed query above — 1,000,000 × 4 × 2,186 = 8,744,000,000 rows read — still land inside the 25 billion included, and at ten million page views become 87.44 billion rows, of which 62.44 billion bill at $0.001 per million: $62.44. A single missing index on a 2,186-row table is a $62 line item. On a table with a million rows it is a bill that needs its own meeting.

$34,895 in eight days, with zero users and no alert

The failure that matters is not slow growth. It is a Durable Object scheduling its own wake-up.

A pre-launch solo founder posted the postmortem to Hacker News on 2026-04-16. His agent object called setAlarm() in onStart() without checking whether an alarm was already pending, so every wake-up scheduled another. Sixty-plus preview deployments each created independent object instances, each running its own copy of the loop. His timeline: began 3 April with zero prior Durable Object usage; peaked 4–5 April at roughly 930 billion row reads a day; found and fixed 11 April; invoice due 15 April, $34,895.

Work the peak day against the published rate. 930,000,000,000 ÷ 1,000,000 = 930,000 million-row units × $0.001 = $930 for one day of row reads. Eight days at that peak is $7,440. The post does not itemise the invoice, so the remaining ~$27,000 is Durable Object requests — one per alarm invocation, $0.15 per million — plus duration at $12.50 per million GB-seconds for objects that never went idle. Row reads do not explain the number. Alarms billing as requests do.

Why nothing warned him is the platform-level lesson, and the reason this sits on the index page rather than in the Durable Objects article: Workers Usage Notifications monitor CPU time. They do not monitor Durable Object row reads or writes, and there is no hard spending cap for Durable Object operations in the dashboard or in a wrangler file. Nothing was going to fire.

The fix from the same post is three lines — read getAlarm() first, call setAlarm() only if it is empty. The two structural fixes alongside it: strip Durable Object bindings out of preview environments entirely, and deploy a separate budget-monitor Worker as a kill switch, because the platform will not.

Pick the binding by the job, not by the brand

The jobThe bindingWhy, in one lineDepth
Relational data you filter, join and sortD1The only binding running SQL over a schema you controlD1
Hot config read everywhere, written rarelyKVEverywhere at once, eventually consistent, cheap reads and expensive writesKV
Files, images, archives — bytes with no queryR2Free egress, $0.015 per GB-month, no per-row meterR2
Serving pages and answering API callsPages FunctionsOne deployment for the page and its API, so no version skewFunctions
Long-lived state one caller at a time must ownDurable ObjectsSingle-threaded, own SQLite. The only strong-consistency primitive hereWorkers and DOs
Work the reader must not wait forQueuesProducer in the request, consumer with its own time budgetAsync
Multi-step jobs that must survive a restartWorkflowsEach step persisted, so a crash resumes rather than restartsAsync
Anything on a clockCron triggers15 minutes of CPU per invocation against 30 seconds for a requestAsync
Fetching pages a plain HTTP client cannotBrowserReal headless Chromium inside the account, billed by browser-hourBrowser
Outbound transactional mailsend_email bindingNo mail vendor and no SMTP credentials in the request pathnot published
Protecting an admin surfaceCloudflare AccessIdentity in front of a route, before the Worker runsnot published

Six documented reasons to keep an application off this platform

Data residency, below Enterprise. Workers gives no choice of region or country for where code executes; the product that constrains it, Regional Services, is an Enterprise add-on. One developer moved a whole TypeScript Workers project to Django over it: "I recently ported an entire TS project from cloudflare workers to a django python app since cloudflare workers don't support choice of region/country when deploying workers." The nuance his complaint misses: Durable Objects do take a jurisdiction on every plan — env.MY_DURABLE_OBJECT.jurisdiction("eu"), with eu, us and fedramp permitted — and then run and persist only there. State can be pinned; request handling cannot. Both are true, of different layers.

D1 latency and reliability, over a year in production. "Using D1 in production for over an year on multiple projects - I can confirm response times to simple queries regularly take 400ms and beyond. On top there's constant network, connection and a plethora of internal errors." A second production user, a year later on a different thread: "D1 reliability has been bad in our experience. We've had queries hanging on their internal network layer for several seconds, sometimes double digits over extended periods (on the order of weeks)."

No transaction across two requests. "Another fun limitation is that a transaction cannot span multiple D1 requests, so you can't select from the database, execute application logic, and then write to the database in an atomic way." His workaround: pack a precondition into the first statement of a batch and make it throw on purpose.

Per-tenant database sharding does not work in practice. The documented one-database-per-customer pattern collapses on the binding model: "It's not possible to set up per-user data in D1. Like in theory you probably could, but the DX infrastructure to make it possible is non-existent - you have to explicitly bind each database into your worker."

The deployment tool, if you live in a monorepo. A developer who moved a Cloudflare stack to Azure gave tooling as the reason, not price: "I found the experience of maintaining and deploying workers to be terrible and so monorepo-unfriendly due to wrangler forced usage for deploys (or at least I haven't found better ways)."

Products get superseded underneath you. Pages, which this request layer runs on, is now something Cloudflare recommends migrating away from — described approvingly: "This is kind of what happened (is happening) with pages right now. Workers gained pretty much all of their features and are now the recommended way to deliver static sites too." One developer cannot follow that recommendation at all: "I had to use Pages since Workers don't support 'Custom domains outside Cloudflare zones'. There's no way I can transfer the domain since I have subdomains tightly integrated with AWS services."

Four people who stayed, at four different scales

Someone who could not code five months earlier shipped the whole stack. "Stack: Next.js 14 + React 18 on Cloudflare Pages, Hono 4.10 API on Cloudflare Workers (60+ route modules), 4x Cloudflare D1 databases (~180 tables total), Neon Postgres via Prisma + Hyperdrive, KV + R2 + Durable Objects + Queues." Four databases and roughly 180 tables is not a toy schema.

A migration off managed Postgres took a week. "In a week, from start to production, I migrated an AWS RDS database to Cloudflare D1 behind an OpenAPI REST interface over HTTPS using itty-router-openapi [1]. This will save me at least $250 pa."

Multi-million monthly actives on SQLite inside Durable Objects. "We serve multi million MAU on sqlite orchestrated through durable objects. It's not the most complex thing in the world but it goes further than CRUD. It costs us such a small amount of money for what it does."

A live multiplayer game, with the cost boundary stated out loud. Answering a challenge that Durable Objects are too expensive for a game: "DO alarms handle the time-based stuff (fleet arrivals, combat resolution, resource ticks) so there's no persistent connection cost. so far costs have been negligible." The caveat is the useful half: that holds because the game is tick-based. Anything realtime wants WebSockets, and the billing changes with it.

The person who built Workers argues against the default choice

"It's almost always better to use Durable Objects storage, rather than D1. Even if you only want a single global database, it's better to implement that as a singleton Durable Object, than by using D1." His reasoning: D1 already is a singleton Durable Object wrapping SQLite, so going direct puts the code in the same place as the data instead of one hop away, and read replication is the only thing D1 keeps that a raw object does not have.

He is as blunt in the other direction about KV, to a developer using it as a datastore: "KV is not a distributed database and is really not intended as a database alternative at all. It's more meant for distributing bits of config globally. Cost aside, writes are way too slow for database-ish use." That is why the KV namespace in this application holds 19 keys and not 19,000.

Against both sits a production dissent from the same D1 thread — "I am running 2 production apps on Cloudflare workers, both using D1 for primary storage. I found the performance ok, especially after enabling Smart Placement" — and an independent measurement from a purpose-built harness landing between the positions: "North America performance (US and Mexico) had ~200ms+ latency per query, spiking to 500ms or higher in the test application I made using workers and D1."

Both sides measured something real. D1's convenience and D1's tail latency are both real, and which dominates depends on whether the Worker and the database end up in the same region. Smart Placement is the one lever that decides it. If a 400 ms tail on a simple query is unacceptable, the read path does not belong on D1.

Symptom, cause, fix

Error strings verbatim, each from a filed report or from a command run against this account.

SymptomCauseFix
too many terms in compound SELECT: SQLITE_ERROR [code: 7500]More than about five UNION ALL terms in one D1 statementSplit it, or use d1.batch()
workers.api.error.script_too_large on deploy, fine locallyThe bundled Pages Functions script exceeds 1 MiB. One report is a 2.4 MB compiled WASM file; another is a blog that crossed 200 postsMove the asset to R2 and fetch it, or split the route into its own Worker
string or blob too big: SQLITE_TOOBIG on a Workflow stepA step output above the SQLite value ceiling — reported at ~200 KB as a Uint8Array, while the same bytes as an ArrayBuffer passWrite the payload to R2, return the key as the step output
Every route returns 500 under wrangler dev --remote, production fineDeclaring a queue producer binding breaks all routes in remote dev, including routes that never touch the queueDevelop locally, or comment the producer out while using --remote
Browser Rendering REST calls return 400, codes 7003 / 7000, token verifiedReported against the REST endpoint with correct account id and permissionsCall the MYBROWSER binding from inside a Worker instead of the REST API
A Durable Object alarm silently stops firing foreverA failed handler leaves a past timestamp in storage, so every later scheduling call sees an alarm set and skipsCompare getAlarm() against Date.now(), not against null
Pages Function returns 500 with an empty body in production only, no logsThe script fails before it can emit outputWrap the handler in try/catch, return the error text, deploy again
Access-fronted API: /api/health works, every scoped call failsThe Access JWT carries an identity that is not a member of the resource requestedMap the service-token identity to a real principal before authorising
Forwarded mail silently never arrivesRecipient providers block Cloudflare's forwarding IP ranges: "most times Outlook just blocks Cloudflare IP ranges and emails never get routed to my Outlook mail box"Send from your own authenticated domain instead of relying on forwarding

The volume: nine pages, seven of them live

PageWhat it settlesStatus
D1 as the spineWhy two SQL databases, one append-onlylive
KV as the fast laneWhat belongs in KV when SQL is already presentlive
R2 as the object storeWhat free egress is worth, and what R2 does not do that S3 doeslive
Pages Functions as the request layerOne deployment for every page and route, and its size ceilinglive
Workers and Durable ObjectsJobs that cannot live in a request, and the objects holding state between themlive
Queues, workflows and cronThree different answers to "later", and which one each job needslive
Browser Rendering as the eyesFetching what a plain client cannot, and what a browser-hour costslive
EmailThe send_email binding, routing rules, and the authentication result that made mail landnot written; /a/cloudflare-os-email redirects here
Access and secret postureWhich surfaces are public, which need the owner key, the one-token modelnot written; /a/cloudflare-os-access redirects here

The capability layer above every binding here — one table of rows, each naming a function, an endpoint, a model or a flow — is documented in 891 tools, zero tool schemas, What a directory row is and The four-step loop.

How the counts on this page were taken

Four commands, run from the repository root on 2026-07-26. The account identifier wrangler prints in error output is redacted.

shell
# 387 JavaScript files under functions/, 214 of them exporting a request handler,
# 271 exported handler functions in total
find functions -name '*.js' | wc -l
grep -rlE 'export (async )?(function|const) onRequest' functions --include='*.js' | wc -l
grep -rhoE 'export (async )?(function|const) onRequest[A-Za-z]*' functions --include='*.js' | wc -l

# 91 tables in the content spine, 12 in the event store
npx wrangler d1 execute loop-content-spine --remote --json \
  --command "SELECT name FROM sqlite_master WHERE type='table'"

# row counts; the meta object in the response carries rows_read and size_after
npx wrangler d1 execute loop-shared-events --remote --json --command \
 "SELECT 'events' t, COUNT(*) n FROM events UNION ALL SELECT 'invocations', COUNT(*) FROM invocations UNION ALL SELECT 'capabilities', COUNT(*) FROM capabilities UNION ALL SELECT 'anchors', COUNT(*) FROM anchors"
# events 400,756 · invocations 159,761 · capabilities 1,026 · anchors 6
# "rows_read": 561549 · "size_after": 1061666816

# three R2 buckets, six KV namespaces on the account
npx wrangler r2 bucket list
npx wrangler kv namespace list
Line 19, Column 1Shell Script

The 387 figure matches the count recorded for this project earlier and is unchanged today. Those four COUNT() terms read 561,549 rows between them — $0.00056 of billable work, and the exact shape of the query that stops being free when the tables are a thousand times larger. COUNT() scans.

9
bindings on the Pages request layer, repeated explicitly for preview
7
sibling Workers holding clocks, durable state, private services and special routes
$5.00
monthly total at one million page views under the published assumptions
2,186×
more rows read by the measured LIKE scan than by the slug index
$34,895
reported eight-day Durable Object invoice after a runaway alarm loop
387
JavaScript files under functions in the published reproducible count
It's almost always better to use Durable Objects storage, rather than D1.
In a week, from start to production, I migrated an AWS RDS database to Cloudflare D1.
References (44)
  1. Cloudflare Workers bindings — Cloudflare, Jul 26, 2026“What is a binding?”
  2. Cloudflare Pages Functions bindings — Cloudflare, Jul 26, 2026“A binding enables your Pages Functions to interact with resources on the Cloudflare developer platform.”
  3. Cloudflare service bindings — Cloudflare, Jul 26, 2026“Isolate services from the public Internet.”
  4. Wrangler configuration reference — Cloudflare, Jul 26, 2026“It is best practice to treat Wrangler's configuration file as the source of truth for configuring a Worker.”
  5. Cloudflare Workers secrets — Cloudflare, Jul 26, 2026“Secrets are a type of binding that allow you to attach encrypted text values to your Worker.”
  6. Cloudflare Workers pricing — Cloudflare, Jul 26, 2026“The Workers Paid plan includes Workers, Pages Functions, Workers KV, Hyperdrive, and Durable Objects usage for a minimum charge of $5 USD per month for an account.”
  7. Cloudflare D1 pricing — Cloudflare, Jul 26, 2026“Rows read 5 million / day First 25 billion / month included + $0.001 / million rows”
  8. Cloudflare Workers KV pricing — Cloudflare, Jul 26, 2026“Workers KV pricing for read, write and delete operations is on a per-key basis.”
  9. Cloudflare R2 pricing — Cloudflare, Jul 26, 2026“There are no charges for egress bandwidth for any storage class.”
  10. Cloudflare Durable Objects pricing — Cloudflare, Jul 26, 2026“and alarm invocations”
  11. Cloudflare Queues pricing — Cloudflare, Jul 26, 2026“Operations are per message, not per batch.”
  12. Cloudflare Workflows pricing — Cloudflare, Jul 26, 2026“Billing for Workflows steps and storage will apply starting August 10th, 2026.”
  13. Cloudflare Browser Rendering pricing — Cloudflare, Jul 26, 2026“Browser hours are shared across all methods.”
  14. Send emails from Workers — Cloudflare, Jul 26, 2026“Send a single email using the send() method on your email binding.”
  15. Durable Object data location — Cloudflare, Jul 26, 2026“Durable Objects can be restricted to a specific jurisdiction by creating a DurableObjectNamespace restricted to a jurisdiction.”
  16. Cloudflare Regional Services — Cloudflare, Jul 26, 2026“Regional Services is an Enterprise add-on.”
  17. Migrate from Pages to Workers — Cloudflare, Jul 26, 2026“Migrate to Workers”
  18. D1 query API reference — Cloudflare, Jul 26, 2026“Returns the query result as an object.”
  19. KV versus D1 benchmark harness — Bruce Harrison, Jun 1, 2023“d1_read Read existing value from D1 16ms”
  20. Workflows (local `wrangler dev`): a ~200 KB `Uint8Array` step output fails with `string or blob too big: SQLITE_TOOBIG`, but the same bytes as an `ArrayBuffer` (or a 2 MB string) succeed — GitHub — cloudflare/workers-sdk, May 29, 2026“Workflows (local `wrangler dev`): a ~200 KB `Uint8Array` step output fails with `string or blob too big: SQLITE_TOOBIG`, but the same bytes as an `ArrayBuffer` (or a 2 MB string) succeed”
  21. Deploying on Cloudflare Pages, script_too_large? — GitHub — nuxt-modules/og-image, Apr 13, 2024“Tried deploying a branch with a simple template, it works well locally, but with the 1mb worker limit on Pages (free) I get the `workers.api.error.script_too_large` error as the compiled-wasm file is 2.4mb.”
  22. Queue producer binding causes 500 errors on all routes when using `wrangler dev --remote` — GitHub — cloudflare/workers-sdk, Jun 18, 2025“When a queue producer is configured in `wrangler.toml`, ALL API routes return 500 Internal Server Error when using `wrangler dev --remote`, even routes that don't use the queue binding.”
  23. Cloudflare Browser Rendering API (Code 7003/7000) Failure in Worker — GitHub — cloudflare/workers-sdk, Oct 3, 2025“Despite verified API token permissions and Account ID, the API consistently returns a 400 error.”
  24. [BUG] Durable Objects alarm not firing due to stale past alarms remaining in storage — GitHub — opennextjs/opennextjs-cloudflare, Oct 7, 2025“If `nextAlarm` is a past timestamp, no new alarm is set, creating a deadlock where `alarm()` never fires and tags accumulate in the database.”
  25. Durable Object alarm loop: $34k in 8 days, zero users, no platform warning — Hacker News, Apr 16, 2026“My DO agent's onStart() handler called this.ctx.storage.setAlarm() on every wake-up without checking whether an alarm was already scheduled.”
  26. Cloudflare recommends migrating from Pages to Workers — Hacker News, Aug 10, 2025“I recently ported an entire TS project from cloudflare workers to a django python app since cloudflare workers don't support choice of region/country when deploying workers.”
  27. Journey to Optimize Cloudflare D1 Database Queries — Hacker News, Apr 7, 2025“Using D1 in production for over an year on multiple projects - I can confirm response times to simple queries regularly take 400ms and beyond. On top there's constant network, connection and a plethora of internal errors.”
  28. Cloudflare's AI Platform: an inference layer designed for agents — Hacker News, Apr 16, 2026“D1 reliability has been bad in our experience. We've had queries hanging on their internal network layer for several seconds, sometimes double digits over extended periods (on the order of weeks).”
  29. Journey to Optimize Cloudflare D1 Database Queries — Hacker News, Apr 7, 2025“Another fun limitation is that a transaction cannot span multiple D1 requests, so you can't select from the database, execute application logic, and then write to the database in an atomic way.”
  30. Journey to Optimize Cloudflare D1 Database Queries — Hacker News, Apr 7, 2025“It’s not possible to set up per-user data in D1. Like in theory you probably could, but the DX infrastructure to make it possible is non-existent - you have to explicitly bind each database into your worker.”
  31. Lowstorage: JSON-based database for Cloudflare Workers and R2 buckets — Hacker News, Dec 3, 2023“I found the experience of maintaining and deploying workers to be terrible and so monorepo-unfriendly due to wrangler forced usage for deploys (or at least I haven't found better ways)”
  32. Journey to Optimize Cloudflare D1 Database Queries — Hacker News, Apr 10, 2025“This is kind of what happened (is happening) with pages right now. Workers gained pretty much all of their features and are now the recommended way to deliver static sites too.”
  33. Cloudflare recommends migrating from Pages to Workers — Hacker News, Aug 10, 2025“I had to use Pages since Workers don't support "Custom domains outside Cloudflare zones" [1]. There's no way I can transfer the domain since I have subdomains tightly integrated with AWS services.”
  34. 5 months ago I'd never coded anything. I now have full-stack analytics platform — Hacker News, Feb 25, 2026“Stack: Next.js 14 + React 18 on Cloudflare Pages, Hono 4.10 API on Cloudflare Workers (60+ route modules), 4x Cloudflare D1 databases (~180 tables total), Neon Postgres via Prisma + Hyperdrive, KV + R2 + Durable Objects + Queues”
  35. Without saying "it's scalable", convince me that Serverless is worth it — Hacker News, Jan 12, 2024“In a week, from start to production, I migrated an AWS RDS database to Cloudflare D1 behind an OpenAPI REST interface over HTTPS using itty-router-openapi [1]. This will save me at least $250 pa”
  36. SQLite Is All You Need — Hacker News, Jul 17, 2026“We serve multi million MAU on sqlite orchestrated through durable objects. It's not the most complex thing in the world but it goes further than CRUD. It costs us such a small amount of money for what it does.”
  37. Show HN: I rebuilt a 2000s browser strategy game on Cloudflare's edge — Hacker News, Apr 15, 2026“DO alarms handle the time-based stuff (fleet arrivals, combat resolution, resource ticks) so there's no persistent connection cost. so far costs have been negligible”
  38. Temporary Cloudflare accounts for AI agents — Hacker News, Jun 20, 2026“It's almost always better to use Durable Objects storage, rather than D1. Even if you only want a single global database, it's better to implement that as a singleton Durable Object, than by using D1.”
  39. OAuth for all — Hacker News, Jun 25, 2026“KV is not a distributed database and is really not intended as a database alternative at all. It's more meant for distributing bits of config globally. Cost aside, writes are way too slow for database-ish use”
  40. Journey to Optimize Cloudflare D1 Database Queries — Hacker News, Apr 7, 2025“I am running 2 production apps on Cloudflare workers, both using D1 for primary storage. I found the performance ok, especially after enabling Smart Placement [1].”
  41. Cloudflare Email Service: private beta — Hacker News, Sep 25, 2025“Cloudflare's email routing has been abused by malicious users for so long that I can no longer reliably use it with my domain, most times Outlook just blocks Cloudflare IP ranges and emails never get routed to my Outlook mail box.”
  42. Configuration inventory reproduced from the production repository — miscsubjects.com, Jul 26, 2026“9 request-layer bindings; 7 sibling Workers; 68 referenced environment names”
  43. Indexed and scanning D1 query comparison — miscsubjects.com, Jul 26, 2026“"rows_read": 1 versus "rows_read": 2186”
  44. Production resource counts — miscsubjects.com, Jul 26, 2026“387 JavaScript files; 91 content tables; 12 ledger tables; 3 R2 buckets; 6 KV namespaces”