Testing the limits of cloudflare D1
Published at 2024-2-25
Testing the limits of cloudflare D1
I’ve been messing around with cloudflare D1 recently, its a serverless sqlite database, built upon CF’s “durable object” platform. It’s currently still in beta with GA scheduled for the “end of quarter one”, I’ve been using it on and off in small projects, noramlly paired with drizzle and have found it generally works well. Prior to this I was mainly using planetscale, which is a much more rounded offering
Compared to other serverless database providers you don’t get a sql connection string, instead you have to use the Cloudflare HTTP api or use a worker / pages function.
Advantages:
- Ok free tier (5mil read, 100,000 writes /day, 5gb), good allowance on $5 workers paid (25billion row reads, 50 million writes, 5gb storage)
- Generally fast if nearby to database - A pages rendered page with a straightforward database read will normally return within 100ms
- ? global read replication at some point
Disadvantages:
- Database’s are limited to 2gb in size at the moment…
- Less polished management interface than providers like planetscale
- Sqlite vs mysql
But how does it perform?
This started when I saw a post on discord about https://neal.fun/infinite-craft/ , a fun game where you can quickly craft new items by combining words and utilising AI calls.
The game became viral and the D1 database stopped responding. Which is a bit odd because the whole advantages of this “serverless” platform is effortless scaling right?
Well it transpires that each D1 database is stored in a single durabal object, so are limited by the capabilities of the durabal object.
In the CF docs we can find that “Each individual Object is inherently single-threaded. An individual Object has a soft limit of 1,000 requests per second.” It also mentions that this will vary on the load.
We can also look in the docs at the queues product (also built upon DO) and see that the max limit is about 400rps
Simple testing from my local machine writing a single 1kb row, CF manages 267 RPS for 2 seconds,

And for reads, this one is doing a count(*) on a ~ 10k table

I was strugling to test for longer as I hit I think I hit a ratelimit and just got 500 returned… I moved to using loader.io to see if it CF was limiting me as I was coming from a single host
Loader.io writes (the loader.io servers are in the US hence the increased latency)
This next test is a repeat of the single write ~ 1kb row, 400 clients ~ 400 rps, it’s strugling here with response times increasing to over a second.
