DEV Community

Cover image for DynamoDB vs Firestore
DynoTable
DynoTable

Posted on • Originally published at dynotable.com

DynamoDB vs Firestore

Is DynamoDB or Firestore better for my app?

Both are fully managed, serverless NoSQL databases, but they solve different problems. Amazon DynamoDB is an AWS key-value and document store tuned for predictable low-latency access at large scale. Google Cloud Firestore is a GCP document database whose defining feature is realtime snapshot listeners and offline-capable mobile and web SDKs. Choose DynamoDB for AWS-native backends; choose Firestore for realtime, client-connected apps.

Characteristic DynamoDB Firestore
Cloud platform Amazon Web Services (AWS) Google Cloud / Firebase (GCP)
Data model Tables of items (key-value and document); attributes on each item Documents grouped into collections; documents hold nested fields and subcollections
Query API Query/Scan via AWS SDK, CLI, or PartiQL; access driven by primary key and indexes Document/collection queries via client and server SDKs, with chained filters and ordering
Realtime sync and offline No native client sync; change capture is via DynamoDB Streams, consumed by your own code (e.g. Lambda) Built-in realtime snapshot listeners; offline persistence and local caching in the Apple, Android, and web SDKs
Indexes Global secondary indexes (GSI) and local secondary indexes (LSI), defined explicitly Automatic single-field indexes plus explicit composite indexes for multi-field queries
Consistency Eventually consistent reads by default; strongly consistent reads optional (and on LSIs); GSI reads are eventually consistent only Strongly consistent queries
Scaling Serverless; on-demand or provisioned throughput; global tables for multi-Region replication Serverless with automatic scaling and multi-region replication
Pricing model Read/write capacity units (RCU/WCU) — provisioned or on-demand — plus storage Per-document reads, writes, and deletes, plus storage, network egress, and index entries read; free daily quota
Best fit AWS-native, high-scale backends with well-defined access patterns Realtime, mobile-first, and client-connected apps on GCP/Firebase

When DynamoDB is the better choice

DynamoDB fits when your stack is on AWS and you want a database that stays fast and predictable as traffic grows. Its capacity model (RCU/WCU, provisioned or on-demand) and single-digit-millisecond access suit high-throughput backends — shopping carts, session stores, event logging, and any workload with well-understood access patterns you can model around a primary key plus GSIs.

It is also the better pick when you need strongly consistent reads on your primary table, tight IAM-based access control, or integration with the wider AWS ecosystem (Lambda, S3 export, streams into analytics). If your clients talk to your own API rather than directly to the database, DynamoDB's lack of a built-in client sync layer is not a limitation.

When Firestore is the better choice

Firestore is the stronger option for realtime and mobile-first apps. Its snapshot listeners push changes to connected clients as soon as data updates, and its Apple, Android, and web SDKs cache data locally so the app keeps working offline and re-syncs when the device reconnects. That makes it a natural fit for chat, collaborative tools, live dashboards, and consumer mobile apps.

It is also a good default when you are already on Google Cloud or Firebase, want strongly consistent queries without opting in per request, or prefer letting clients query the database directly (guarded by security rules) instead of building an API tier. Its automatic indexing removes some upfront schema-design work at small scale.

What a Firestore listener becomes in DynamoDB

The table above says DynamoDB has no native client sync. This is the size of that
sentence. In Firestore, a live view of open orders is one call:

import {collection, onSnapshot, query, where} from 'firebase/firestore';

const q = query(collection(db, 'orders'), where('status', '==', 'open'));
const unsubscribe = onSnapshot(q, (snapshot) => {
  snapshot.docChanges().forEach((change) => {
    if (change.type === 'added') add(change.doc.data());
    if (change.type === 'modified') update(change.doc.data());
    if (change.type === 'removed') remove(change.doc.id);
  });
});
Enter fullscreen mode Exit fullscreen mode

DynamoDB has no counterpart to that at any layer, and PartiQL is irrelevant here
because the gap is not in the query language. What replaces it is a pipeline you build,
deploy and operate:

  1. A stream on the table, with StreamViewType: NEW_AND_OLD_IMAGES so a change carries enough context to diff. Records live in the stream for 24 hours.
  2. A Lambda event source mapping over it. One function instance reads each open shard in sequence-number order.
  3. An API Gateway WebSocket API and a connections table. $connect stores the connection id plus whatever the client subscribed to; $disconnect deletes it.
  4. The matching step, which is the real work. A DynamoDB stream is per table, not per query. Firestore's server evaluates status == 'open' against every change for you; here that predicate lives in your handler, and it has to run against every subscription for every changed item.
  5. The push, via PostToConnectionCommand, plus handling GoneException for the clients that vanished without calling $disconnect.

Three Firestore behaviors have no line item in that list at all.

The initial snapshot. onSnapshot delivers the current result set first and deltas
after. A stream delivers only deltas, so each client has to issue its own Query to
seed itself and then reconcile that against changes that arrive while the seed is in
flight.

Offline. Firestore's Apple and Android SDKs enable offline persistence by default,
the web SDK opts in, and local writes notify listeners before the data reaches the
backend, flagged with metadata.hasPendingWrites. Nothing in DynamoDB does this. Your
client either has a connection or has nothing.

Ordering. Firestore guarantees clients never see updates out of order relative to
the order the database committed them. DynamoDB Streams guarantees ordering per item,
across all modifications to the same primary key, and not across items. Two items
changed in one logical operation can reach a client in either order.

The bill moves too, in both directions. Firestore charges a read "each time a document
in the result set is added or updated", so a chatty listener is a metered thing, and
with offline persistence on, a listener disconnected for more than 30 minutes is
charged "as if you had issued a brand-new query". DynamoDB charges you nothing to keep
a client watching, because it has no idea a client is watching. You pay for the write,
the stream read, the Lambda invocation, and the WebSocket connection minutes instead.
That is not obviously cheaper. It is just yours to run.

DynoTable does not close this gap and no desktop client could. Where it helps is step
four, before you deploy it: the subscription filter your handler evaluates is a query
against real keys, and the SQL Workbench compiles a statement to DynamoDB's native
Query and Scan planned against your actual keys and indexes, so you can see whether
status = 'open' resolves to a GSI query or degrades into a table scan while it is
still a line of SQL rather than a Lambda in production.

Working with DynamoDB

Once you have chosen DynamoDB, DynoTable is a desktop client for working with your tables directly — browsing and editing items, running queries, and building expressions without hand-writing every request. It reads your standard AWS credentials and talks to DynamoDB in your own account.

If you are still assembling requests by hand, the free DynamoDB Expression Builder generates key conditions, filter expressions, and update expressions with the correct attribute-name and value placeholders for the AWS SDK, CLI, boto3, and PartiQL. DynoTable is a closed-source commercial app; this page is a neutral technical comparison, not a benchmark.

FAQ

Should I use DynamoDB or Firestore for a mobile app?

For a mobile app that needs realtime updates or offline support, Firestore is usually the more direct choice: its Apple, Android, and web SDKs include realtime snapshot listeners and offline persistence out of the box. DynamoDB has no native client sync layer — you would build realtime behavior yourself using DynamoDB Streams and your own backend. DynamoDB is the better fit when clients call your own API rather than the database directly.

Which is cheaper, DynamoDB or Firestore?

Neither is universally cheaper; they bill on different axes. DynamoDB charges for read/write capacity units (provisioned or on-demand) plus storage, so cost tracks throughput. Firestore charges per document read, write, and delete, plus storage, egress, and index entries read, with a free daily quota. Read-heavy or realtime-listener-heavy workloads can accumulate Firestore document-read charges, while steady high-throughput workloads often model more predictably on DynamoDB. Estimate against your own access pattern using each provider's current pricing page.

Does DynamoDB have realtime sync like Firestore?

Not natively on the client. Firestore's snapshot listeners stream changes to connected apps automatically. DynamoDB's equivalent building block is DynamoDB Streams, which captures item-level changes; you consume that stream with your own code (for example an AWS Lambda function) to push updates onward. It is realtime change capture, but you build the delivery to clients yourself.

Related

References

Last verified 2026-07-13 against the AWS DynamoDB Developer Guide and the Google Cloud Firestore documentation. Google Cloud Firestore is a trademark of its respective owner; referenced here for identification only.

Top comments (0)