FokosDB: A strongly consistent bottomless storage database ontop of Cloudflare Durable Objects | Lambros PetrouIn this post I do a deep dive on a database I built ontop of Cloudflare Durable Objects (DOs) and the rest of Cloudflare Developer Platform.
Let’s clarify a few things first.
Is FokosDB production ready? Not yet , but it will be soon.
Is FokosDB going to be fast and suitable for all use-case? No, read the Tenets and Goals sections below.
Is FokosDB going to be enough for many applications on Cloudflare Workers? Absolutely.
Is FokosDB really bottomless storage? Yes, as long as Durable Objects can be created in your account.
Is FokosDB an official Cloudflare product? No, hence not officially supported by Cloudflare.
Is this yet another vibe-slop? No. I did a lot of iterations on the design, and researched a lot of similar databases before I settled on the following tenets and goals. A lot of the code is AI generated (see AI productivity boost section) but I reviewed every single line, and most likely I modified every single line in some way or another.
Having said that, the code is still quite prototype-ish and I plan to refactor it, since the goal so far was to get a first version of the database working.
This article is written word by word by me. 😉
FokosDB is the database I want to use in production for my projects on Cloudflare’s Developer Platform.
Table of contents
Tenets
Goals and API
Why not xyz
Platform constraints
System architecture overview<br>Life of a FokosDB request
Data partitions
Topology invariants
Splits and hash key promotions<br>Hash key promotions
Distributed transactions
Topology encoding and caching<br>Related work
FokosDB encoded topology
Future work<br>Performance optimizations
Wishlist for the platform
Show me the numbers
AI productivity boost
Conclusion
Tenets<br>Applications, especially data products, deployed on serverless platforms have to make trade-offs due to the different constraints of the platform, and Cloudflare’s Developer Platform is no different.
These tenets drive the trade-offs in the architecture and characteristics of the database.
Bottomless storage.<br>Within practical limits I don’t want to be constrained on the total overall storage used by the database. I should be able to store TBs of data without issues.
Strong consistency.<br>Eventual consistency makes everything harder to reason about. If I update item A and immediately read item A, I want to see its latest version.
Eventual consistency could be optional if it gives significant performance benefits, but should be opt-in.
Throughput should scale across different items.<br>Even if the per-item throughput will be constrained, throughput across thousands or millions of items should scale up linearly to the number of items.
Good enough performance.<br>Network round-trips are inevitable when running at the edge and wanting to reach durable storage, but we should reduce them as much as possible.
Ballpark read item latency: same country less than 50ms, same region less than 200ms.
Managed scaling.<br>Scaling should be automatic without manual intervention. Just write and read data.
Goals and API<br>These goals drive the implementation and API provided.
Each item is identified by a hash key and a sort key .<br>When items have the same hash key they should have different sort keys, and items having the same hash key are sorted lexicographically based on their sort key allowing range queries within the hash key.
Each item is less than 1MB (default limit is 500KB). For larger blobs I will implement integration with R2 (object storage).
Scalability is achieved by sharding across many different items, ideally with different hash keys to eliminate hot partitions as much as possible.<br>The system architecture optimizes for hash key sharding, even if you can have unlimited number of range keys within a hash key.
Core operations: putItem, getItem, deleteItem, queryItems (soon).<br>All write operations support conditional checks.
Distributed transactions across items: transactWriteItems, transactReadItems.<br>Restrictions on number of items and total request size apply.
Trade-offs are based on these load profiles: a) 100-500 GB total storage, and b) 100 TB+ total storage, both assuming well spread out hash keys.
My favourite database is Amazon DynamoDB in case it wasn’t clear so far.
Why not xyz<br>Why did I build a new database instead of using something that already exists?
Cloudflare offers several storage products: D1, Durable Objects, Hyperdrive+Postgres/MySQL, R2, Workers KV
Each one of these comes with its own set of constraints and limitations, but none of them satisfies the tenets and goals above.
I also wanted to push Durable Objects and the Developer Platform as much as I can in order to discover what primitives we should go and build next natively into the platform.
For context, my day job is at Cloudflare’s Developer Platform.
Finally, because it’s fun.
Platform constraints<br>Before we dive into the...