Deno KV vs. Cloudflare Workers KV, Upstash Redis, AWS DynamoDB, and Google Firestore
More developers are choosing to host stateful applications at the edge for a variety of reasons β higher availability with more points of presence, lower latencies due to being physically closer to users, controlling data residency for compliance, and more.
Our managed Deno KV, now in open beta, is our key value store with read-committed, sequentially consistent, multi-region replicas, that’s built on FoundationDB and baked right into the runtime. You can add state without configuring a database or juggling API keys in as little as a single line of code:
const kv = await Deno.openKv();
We wanted to see how Deno KV stacked up against other leading distributed serverless databases on dimensions such as read/write latencies and pricing, as well as qualitative characteristics, such as developer experience:
If you’d like us to evaluate other serverless databases, please let us know in the issues.
Methodologies for measuring latencies
We built a benchmarking app to measure real-time read and write latencies for the five serverless databases. Each database is seeded with 14,275 key-value pairs. Anytime the app receives a request from a browser, it initiates five serverless functions (each corresponding and colocated, if possible, to the serverless database it’s measuring) that will:
- perform a simple read operation to warm up the instance (not measured)
- read a random 10 records out of 14,275 total key-value pairs from the database
(the size of any combination of 10 records will always be 189KB) to avoid
caching where possible, and measures it as
read
latency - alter the 10 records, then concurrently remove the old 10 records from and
write the altered 10 records to the database, which is measured as
write
latency - store measured latencies in a main database, from which percentile data is calculated and displayed in the frontend
Consistency and transaction isolation levels
Since we selected these serverless database based on popularity, we recognize that not all reads and writes are equal, as not all databases offered the same consistency and transaction isolation levels:
Database | Consistency Level | Transaction Isolation |
---|---|---|
AWS DynamoDB | Eventual | Read-Committed |
Upstash Regional | Eventual | None |
Google Firestore | Strong | Serializable |
Cloudflare KV | Eventual | None |
Deno KV | Strong | Serializable |
read
and write
latencies
Isolating To ensure we’re only measuring read and write latencies, we:
- Minimized network latency by having all logic in edge functions colocated with corresponding databases (where possible):
Database | Serverless Function | Region |
---|---|---|
AWS DynamoDB | AWS Lambda | us-west-2 |
Upstash Regional | AWS Lambda | us-west-2 |
Google Firestore | Google Cloud Function | us-west1 |
Cloudflare KV | Cloudflare Worker | NA* |
Deno KV | Deno Deploy Isolate** | us-east4-a |
- Excluded latency between browser to server by measuring read and write within the serverless function
- Excluded cold start time by warming up the database connection with an initial read
- Recorded timestamps right before and after the read and write
With all of these considerations, the recorded read and write latencies should reflect the time it takes the serverless database to complete its operation.
Results
We’ll dive into the performance more in detail later in this post, but here are the results at a glance.
View the app or check out the source code.
Comparing performance and pricing
Before we dive into analysis for each serverless database, let’s compare them on performance and pricing.
Performance
Below is the data collected from our app with a sample size of 10,000 transactions. Note that Cloudflare KV’s longer cache expiration resulted in a smaller sample size of 5,712 transactions.
Database | Read latency, 50th percentile (ms) | Read latency, 90th percentile (ms) | Read latency, 99th percentile (ms) |
---|---|---|---|
AWS DynamoDB | 298 | 480 | 700 |
Upstash Regional | 19 | 35 | 139 |
Google Firestore | 200 | 299 | 699 |
Cloudflare KV* | 341 | 426 | 742 |
Deno KV | 22 | 50 | 90 |
Upstash Redis performed the best with Deno KV in close second, and DynamoDB and Firestore lagging behind. Cloudflare KV performed the worst, due to its heavy caching and eventual consistency model, which isn’t well suited for measuring propagated changes with frequent reads and writes. In fact, their documentation explicitly states that changes may take up to 60 seconds to be visible due to cache timeouts.
Database | Write latency, 50th percentile (ms) | Write latency, 90th percentile (ms) | Write latency, 99th percentile (ms) |
---|---|---|---|
AWS DynamoDB | 199 | 377 | 560 |
Upstash Regional | 86 | 120 | 279 |
Google Firestore | 275 | 475 | 826 |
Cloudflare KV | 538 | 612 | 866 |
Deno KV | 62 | 96 | 166 |
Deno KV led the batch in write latencies with Upstash Redis as a close second, followed by AWS DynamoDB, Google Firestore, and Cloudflare KV.
Pricing
Database | Reads (million) | Writes (million) | Storage (GiB per month) | Network (GiB) |
---|---|---|---|---|
AWS DynamoDB | $0.25 (4kb units) | $1.25 (1kb units) | $0.25 | - |
Upstash Regional | $2 | $2 | $0.25 | $0.03 |
Upstash Global* | $4 | $4 x N | $0.25 x N | $0.10 |
Google Firestore** | $0.3 | $0.9 | $0.15 | - |
Cloudflare KV | $0.5 | $5 | $0.5 | $0 |
Deno KV | $1 (4kb units) | $2.5 (1kb units) | $0.5 | - |
In terms of reads and writes, AWS DynamoDB and Google Firestore are the most competitive, while Upstash is the most expensive (especially global). Cloudflare reads are relatively competitively priced, while their writes are the most expensive at $5 per million writes. Deno KV is in the middle with $1 per million reads and $2.5 per million writes.
For storage, Google Firestore was cheapest at $0.18 per GiB per month. On the higher end is Cloudflare and Deno at $0.5 GiB per month.
Upstash Redis
Upstash, a serverless data platform, offers a key value store through Upstash Redis.
At a glance:
- Atomic Operations: β
- Global replication: β
- Locations: 8
- Consistency control via API: β
Upstash Redis uses a leader-based replication mechanism and can only provide eventual consistency.
Developer experience
Overall, using Upstash Redis is the “standard” serverless experience β you
provision a database and connect to it via a Redis client library with unique
host
and password
variables defined in your environment. There’s neither
anything frustrating nor is there anything particularly delightful about the
experience of setting up and connecting a serverless database.
AWS DynamoDB Global Tables
AWS DynamoDB Global Tables is a fully managed serverless distributed database from Amazon.
At a glance:
- Atomic Operations: β
- Global replication: β
- Locations: 17
- Consistency control via API: β
As expected from AWS, this serverless database solution is fully featured and offers developers flexibility in configuring it down to the smallest details.
Developer Experience
It should come as no surprise that dealing with anything AWS will be met with
frustration and headaches. Setting up the database took a few clicks and some
configuration, nothing too out of the ordinary. However, when connecting to
DynamoDB, the biggest issue was bumping against stale and obtuse documentation
with @aws-sdk/lib-dynamodb
and figuring out the right path through a
GitHub issue response
from one of the maintainersβ¦
When developing locally, if you want to use a local instance of DynamoDB for testing and iterating, there’s another step you have to take, which is to download and install “DynamoDB local”. It’s good to know that it’s possible to develop against a local version of DynamoDB, but unfortunately its a tedious multi-step setup process.
Google Firestore
Google Firestore, part of the Firebase development platform, is a serverless non-relational database.
At a glance:
- Atomic Operations: β
- Global replication: β
- Locations: 23
- Consistency control via API: β
Similar to AWS DynamoDB, Google Firestore is featureful and offers a ton of configuration and flexibility to meet a wide range of developer needs.
Developer Experience
Aside from the typical database provisioning steps that come with all serverless
platforms, Google Firestore is a little bit simpler than the previous solutions,
in that there’s one Firestore database per project. This makes connecting to the
database simpler, since you just need new Firestore()
and don’t have to worry
about connecting to the “wrong” database.
Aside from that, interfacing with Firestore via a client library was relatively straightforward.
Cloudflare Workers KV
Cloudflare Workers KV is a low latency serverless key value storage.
At a glance:
- Atomic Operations: β
- Global replication: β
- Locations: 300
- Consistency control via API: β
Cloudflare Workers KV is designed to be eventually consistent, and uses a global cache system to offer quick reads on data that doesn’t change often. It does not offer atomicity nor consistency control. For those, Cloudflare recommends Durable Objects.
Developer Experience
Cloudflare Workers KV was pretty standard to provision and configure through the
Cloudflare Workers website. Connecting to Cloudflare Workers KV is relatively
straightforward, as well, using KV namespaces and the right settings in a config
file, wrangler.toml
.
Deploying Cloudflare Workers is a little tricky, as we need to bundle the
function in order to deploy it to Cloudflare with
wrangler
. This adds a
fold of complexity when testing and troubleshooting between local dev and prod
environments, since bundling and sourcemapping happens on deployment.
Global Deno KV
Deno KV on Deno Deploy is built on FoundationDB and is built right into the runtime.
At a glance:
- Atomic Operations: β
- Global replication: β
- Locations: 3
- Consistency control via API: β
Being atomic was a prerequisite for Deno KV so it impacted how we designed the API. There’s currently three regions, and we plan to add more.
Finally, you can choose how consistent you want your reads to be, depending on your performance and data integrity needs.
Developer Experience
Connecting to Deno KV was the fastest and easiest, as it only took a line of code. There were no separate steps to provision or configure a database, or to juggle API keys.
On top of that, the local environment and production environment on Deno Deploy are the same, making testing and deployment a seamless experience.
What’s next?
Our managed version of Deno KV, built on FoundationDB, not only offers a simple zero config, ACID-compliant JavaScript API for persistent data, but also offers some of the best performance among other serverless databases.
In the past months, we’ve continued to add features to Deno KV, such as the ability to remotely connect to a managed Deno KV instance, continuous backups to S3 and GCS, and point-in-time recovery. Deno KV, alongside, Deno Queues, Deno Cron, and access to npm, means you can build for the web faster with minimal boilerplate.
As we continue to improve Deno KV towards a generally available release, we welcome your feedback.
We just released Deno KV Watch! Building real-time apps such as notifications, newsfeeds, multiplayer games, and more just got easier.