Cloudflare costs

What each Cloudflare resource costs, the free-tier daily limits, and how EmuView's architecture maps onto them.

#Cloudflare costs

Cloudflare bills by operation, not by server. Understanding which operations your requests trigger — and which quotas they draw from — is the foundation for everything else in this section.

#What each resource costs

Resource What counts Why it adds up
D1 rows read Every row the database scans, not just rows returned An unindexed filter scans the entire table to return one page
D1 rows written Every row inserted or updated, plus one write per index entry A record insert on a collection with 3 indexes writes 4+ rows
Worker CPU time Milliseconds of actual compute per invocation Excludes I/O wait — a request can take 500 ms wall-clock and use 3 ms CPU
Worker invocations Each request that reaches a worker Includes service-binding calls between your own workers
KV operations Reads, writes, deletes, and lists, each counted separately One read per request across all traffic adds up fast
Durable Object requests Each call into a Durable Object Per-request patterns (rate limiting) mean one call per API request
R2 operations Class A (writes, lists) and Class B (reads), billed at different rates Deletes are free; reads are 10× cheaper than writes

#Free-tier limits

These are the daily and monthly caps on Cloudflare's free plan.

Resource Free-tier limit Period
D1 rows read 5,000,000 day
D1 rows written 100,000 day
D1 storage 5 GB total
Worker requests 100,000 day
Worker CPU time 10 ms per invocation
KV reads 100,000 day
KV writes 1,000 day
Durable Object requests 100,000 day
R2 Class A operations (writes, lists) 1,000,000 month
R2 Class B operations (reads) 10,000,000 month
R2 storage 10 GB month
Note

The asymmetry matters: you get 50× more D1 reads than writes per day, and 100× more KV reads than writes. Write-heavy workloads hit limits far sooner than read-heavy ones.

The Performance tab's fuel gauges track five of these: worker requests, D1 rows read, D1 rows written, KV reads, and Analytics Engine writes. The rest — Durable Object requests, KV writes, CPU time — are not gauged; watch them in the Cloudflare dashboard. D1 and R2 storage are tracked on System → Monitor rather than in the gauges, since they are standing levels rather than daily rates.

#Storage does not shrink when you delete

D1 storage is the one quota with a hard ceiling and no way to buy past it on the free plan, so it is worth knowing how it behaves:

  • EmuView soft-deletes records by default — the row remains, marked with deleted_at, and still occupies space until purged.
  • Even a hard delete does not shrink the database file. SQLite marks the pages free for reuse but does not return them to the OS, so the reported database size stays flat until new data fills the gap.

So "I deleted a million records and storage didn't move" is expected, not a bug. Monitor → Collections shows soft-deleted rows in their own column so you can see how much of a collection is tombstones.

Because storage only ever moves in one direction in practice, the number that matters is the rate. System → Usage → Cost & Usage tracks growth per day and projects the date you would hit the ceiling; see Monitoring.

#How EmuView maps onto these quotas

Every EmuView request has a baseline cost before your own queries run. Knowing the fixed costs helps you read a cost receipt without alarm.

Architecture piece What it consumes Per
Pages app → gateway service binding 1 worker invocation (the gateway call is billed like any request) request
Session cache 1 KV read authenticated request
Rate limiter 1 Durable Object call API request
Auth and permission resolution Several D1 queries (session, user, roles, policies) authenticated request
Analytics datapoint 1 Workers Analytics Engine write request

So a single authenticated API call typically costs: 2 worker invocations (Pages + gateway), 1 KV read, 1 DO call, a handful of D1 queries for auth, and then whatever your actual operation reads or writes. This baseline is normal — the numbers to watch are the ones that scale with your data, above all rows read.

#Where to look next