Skip to main content
Deno KV benchmarked against other serverless database solutions.

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
Note that both Upstash Redis and Cloudflare KV are key value stores that do not support serializability. All databases were configured with default settings. For specifics, here’s the Terraform file for DynamoDB, Firestore, Cloudflare. Upstash was provisioned through their website and Deno KV did not require a separate configuration step.

Isolating read and write latencies

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
*Cloudflare KV is global and does not have a primary region. **We spun up an isolate in the same region as Deno KV primary region through a virtual machine proxy.
  • 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.

Read latencies

Read latencies at 99th percentile

Write latencies

Write latencies at 99th percentile

The 99th percentile for read and write latencies with sample size of 10,000, except for Cloudflare KV, which had a sample size of 5,712 due to caching. Tail latencies matter because they can negatively affect user experience and confidence.

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 -
* N denotes number of regions. ** Google Firestore pricing is for single region `us-west1`. Network costs “-” indicate pricing is incurred by the platform, but not explicitly defined for the database product.

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.