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 |
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
- The Performance dashboard shows your live position against every limit above.
- Index tuning covers the highest-impact fix for the largest quota (rows read).