Cloudflare D1 Pricing Calculator and Batch Limits
Cloudflare D1 pricing calculator. Turn users and queries into rows read and written, check the Free plan's daily limits, and size batch inserts under D1's caps.
- Runs in your browser
Checked
01Tool
Tool
What D1 costs
Paid plan, a month
$5.00
The Workers Paid minimum plus D1 usage past its allowances.
Rows read a day
400K
Rows written a day
5,000
Free plan
Fits
Costs nothing
Paid plan, line by line
- Workers Paid minimum
- $5.00
- D1 rows read 12M of 25B included
- $0.00
- D1 rows written 150K of 50M included
- $0.00
- D1 storage 0.2 GB of 5 GB included
- $0.00
- Total a month
- $5.00
Free plan limits, closest first
- D1 database size40%
0.2 GB of 0.5 GB
- D1 databases10%
1 of 10
- D1 rows read8%
400K of 5M a day
- D1 rows written5%
5,000 of 100K a day
- D1 storage, all databases4%
0.2 GB of 5 GB
How many rows fit in one INSERT
Rows per INSERT
14
98 bound values in each statement
Statements
72
Worker invocations
2
const size = 14
const length = Math.ceil(rows.length / size)
const [first, ...rest] = Array.from({ length }, (_, i) =>
db.insert(table).values(rows.slice(i * size, (i + 1) * size)),
)
if (first) await db.batch([first, ...rest])The calculator counts each statement in a batch as one query toward the limit per invocation; Cloudflare's docs do not say how a batch counts.
02Guide
How it works
How D1 counts rows
Rows read are rows scanned, not rows returned. SELECT * FROM users reads every row, and so does a WHERE on a column without an index, even when it returns one row. Rows written count each row an INSERT, UPDATE or DELETE changes, and schema changes can count as both. Row size does not matter: a wide row and a narrow one count the same.
Every query's result carries a meta object with rows_read and rows_written. Run your real queries through wrangler d1 execute and read those numbers instead of guessing. Queries from the dashboard and Wrangler are billed like any other.
Indexes cut reads and add a write
An index on a column you filter or join on lets D1 find the matching rows without reading the rest of the table. A write that sets an indexed column also writes to the index, and that counts as a second row. Set the indexes each write touches to the number of indexes on the columns your writes set. Cloudflare says the saved reads offset the extra write in nearly all cases.
Too many SQL variables
D1 limits how many values a single query can bind, and the limit holds for each statement inside db.batch() too. A multi-row INSERT binds rows times columns values, so it reaches the limit sooner than it looks. The error reads too many SQL variables at offset, and Drizzle has an open issue asking it to chunk inserts on its own.
There are two fixes. Chunk the rows so each INSERT stays under the limit, and send the chunks in one db.batch(), which runs them in order as one transaction and rolls back if any fails. For lookups and updates over a list of ids, bind the list as one JSON string and expand it in SQL with json_each, so the whole list takes a single parameter.
At the Free plan's limits
Past the daily read or write limit, every D1 query on the account fails until the reset at 00:00 UTC. Storage works differently: once it is full, you have to delete data before you can insert again, create tables or add indexes. Moving to Workers Paid lifts the limits, typically within minutes.
D1 or Postgres through Hyperdrive
D1 is built on SQLite. Each database runs one query at a time and has a size cap that Cloudflare cannot raise, because D1 is designed for many smaller databases, such as one per tenant. An app that keeps every tenant in one large schema may suit Postgres through Hyperdrive better. The Workers pricing calculator prices either choice beside the rest of a Worker's bill.
03Rates
The numbers it uses
| Item | Rate | Source |
|---|---|---|
| D1 rows read, Free Rows scanned, not rows returned. | 5 million a day | developers.cloudflare.com |
| D1 rows read, Paid | 25 billion a month included, then $0.001 per 1 million rows | developers.cloudflare.com |
| D1 rows written, Free A write that sets an indexed column adds a row for the index. | 100,000 a day | developers.cloudflare.com |
| D1 rows written, Paid | 50 million a month included, then $1.00 per 1 million rows | developers.cloudflare.com |
| D1 storage, Free All databases together, tables and indexes. | 5 GB in total | developers.cloudflare.com |
| D1 storage, Paid | 5 GB included, then $0.75 per GB-month | developers.cloudflare.com |
| Item | Rate | Source |
|---|---|---|
| Bound parameters per query Applies to each statement inside a batch. | 100 | developers.cloudflare.com |
| Columns per table | 100 | developers.cloudflare.com |
| SQL statement length | 100,000 bytes | developers.cloudflare.com |
| Queries per Worker invocation, Free | 50 | developers.cloudflare.com |
| Queries per Worker invocation, Paid | 1,000 | developers.cloudflare.com |
| Database size, Free | 0.5 GB | developers.cloudflare.com |
| Database size, Paid Cloudflare cannot raise it. | 10 GB | developers.cloudflare.com |
| Databases per account, Free | 10 | developers.cloudflare.com |
| Databases per account, Paid Cloudflare can raise it on request. | 50,000 | developers.cloudflare.com |
| Storage per account, Free | 5 GB | developers.cloudflare.com |
| Storage per account, Paid Cloudflare can raise it on request. | 1,000 GB | developers.cloudflare.com |
| Item | Rate | Source |
|---|---|---|
| Workers Paid plan | $5.00 a month minimum | developers.cloudflare.com |
| Worker requests, Free Resets at 00:00 UTC. | 100,000 a day | developers.cloudflare.com |
| Worker requests, Paid | 10 million a month included, then $0.30 per 1 million requests | developers.cloudflare.com |
| Static asset requests Billed at the request rate while Workers Caching is on. | Free and unlimited | developers.cloudflare.com |
| CPU time, Free | 10 ms per request | developers.cloudflare.com |
| CPU time, Paid | 30 million ms a month included, then $0.02 per 1 million ms | developers.cloudflare.com |
| CPU per Cron Trigger run, Free | 10 ms per run | developers.cloudflare.com |
04Questions
Questions
- How much does Cloudflare D1 cost?
- D1 bills rows read, rows written and storage, and nothing for compute time or egress. The Workers Paid plan includes a monthly allowance of each and charges per million rows and per GB-month past it. The calculator shows how close your load is to each allowance.
- Is Cloudflare D1 free?
- Yes. D1 is on the Workers Free plan, with daily limits on rows read and written and caps on storage, database size and the number of databases. Cloudflare says the Free plan will always include D1 for prototyping.
- What happens when I hit D1's Free plan limits?
- Past the daily read or write limit, every D1 query on the account returns an error until the limits reset at 00:00 UTC. Past the storage limit, you have to delete data before you can insert, create tables or add indexes again. Upgrading to Workers Paid lifts the limits, usually within minutes.
- Why do I get 'too many SQL variables' on D1?
- D1 caps the values one query can bind, and a multi-row INSERT binds one value per column per row, so a large insert passes the cap quickly. The error reads too many SQL variables at offset. Split the insert into chunks under the cap, or pass a list as one JSON value and expand it with json_each.
- How many rows can I insert in one D1 query?
- Divide D1's cap on bound parameters by the values each row binds, and round down. Count every column the INSERT sets, including ones your ORM fills in. The batch calculator above does the division and writes a Drizzle snippet that chunks the rows.
- Do indexes make D1 cheaper or more expensive?
- Usually cheaper. An index lets a filtered query read a few rows instead of the whole table. Each write that sets an indexed column writes one extra row for the index, and Cloudflare says the saved reads offset that in nearly all cases.
05Sources
Sources
Every fact on this page was read from these pages on .
- Cloudflare D1 docs, Pricingdevelopers.cloudflare.com/
d1/ platform/ pricing/ - Cloudflare D1 docs, Limitsdevelopers.cloudflare.com/
d1/ platform/ limits/ - Cloudflare D1 docs, D1 Databasedevelopers.cloudflare.com/
d1/ worker-api/ d1-database/ - Cloudflare D1 docs, Query JSONdevelopers.cloudflare.com/
d1/ sql-api/ query-json/ - Cloudflare Workers docs, Pricingdevelopers.cloudflare.com/
workers/ platform/ pricing/ - Drizzle ORM issue 2479, D1 too many SQL variables at offsetgithub.com/
drizzle-team/ drizzle-orm/ issues/ 2479
Found something out of date? Tell us.
Nuxter
Building a SaaS on Nuxt?
Nuxter keeps its app's tables in Postgres through Hyperdrive and gives D1 only Nuxt Content's pages, so a Nuxter app's D1 reads come from the docs and pages it serves.