open-context open-context
September 13, 2026 · 7 min read

Firestore or DynamoDB for a Serverless MCP Context Store

For a serverless MCP context store, pick Firestore if you're already on Google Cloud and want documents to just work with no consistency workaround required; pick DynamoDB if you're on AWS or want single-digit-millisecond reads at any scale, and accept that guaranteeing read-your-writes there costs twice the read capacity of a default read. Both are two of open-context's 15 supported context-store backends, both need zero servers to run or capacity to size, and both go through the same shared interface — so save_context, recall_context, and the rest of the MCP tools behave identically no matter which one is active.

Key takeaways

  • Firestore and DynamoDB are two of open-context's 15 supported backends, and both are genuinely serverless: no database process to run, no capacity to pre-provision.
  • Both connect through the same DocumentDriver interface — six methods (connect, close, ping, get, put, remove, list) — which is why the CLI, web UI, and MCP tools work identically once either is wired up.
  • DynamoDB is eventually consistent by default, so open-context's driver forces ConsistentRead: true on every read to guarantee getContext sees data immediately after saveContext — and AWS bills a strongly consistent read at twice the capacity of an eventually consistent one.
  • Firestore reads are strongly consistent by default, so open-context's Firestore driver needs no equivalent workaround or extra cost.
  • Neither backend has a portable case-insensitive substring predicate, so recall_context and search_contexts filter in memory after reading the whole collection — the same tradeoff Redis and MongoDB make, and one a SQL backend avoids at scale.

Two different shapes of "serverless"

"Serverless" means something slightly different on each cloud, and that difference shows up the moment you connect. Firestore is Google Cloud's managed document database: there's no table, no partition key, no billing mode to pick — you point a client at a project ID and start writing documents. DynamoDB is AWS's managed key-value and document store, and its serverless mode is on-demand capacity: pay-per-request pricing with no throughput to provision up front, so you don't estimate a workload's peak load ahead of time (Amazon DynamoDB: On-Demand pricing). Both remove the operational surface a self-managed Postgres or Redis instance would need — no patching, no failover to configure — but DynamoDB still has a concept of a table you connect to, where Firestore's collections exist only once something is written into them.

How open-context actually talks to each one

Both drivers implement the same six-method DocumentDriver interface that also backs MongoDB, Redis, and an in-memory adapter used in tests. Everything else — search, tag filtering, ordering, cascading a bubble delete across its contexts — is written once in the shared document adapter, so adding either backend meant writing a driver, not reimplementing the storage contract.

The Firestore driver stores contexts and bubbles in two collections, oc_contexts and oc_bubbles, and authenticates through Google's Application Default Credentials chain rather than a secret embedded in the connection string. The DynamoDB driver puts both collections in one table, split by a partition key (CONTEXT or BUBBLE) so listing either collection is a targeted Query against one partition instead of a full-table scan — and on first connect, if that table doesn't exist yet, it creates one in PAY_PER_REQUEST billing mode and waits for it to report ACTIVE before continuing.

The consistency difference that actually costs you

This is the one place the two backends genuinely diverge, and it's a correctness issue before it's a cost issue. DynamoDB reads are eventually consistent by default — a read shortly after a write can come back stale or empty. That would break open-context's read-your-writes guarantee, the same one every backend in the conformance suite has to satisfy: call getContext right after saveContext, and it must see the write. So the DynamoDB driver passes ConsistentRead: true on every GetCommand and QueryCommand. The tradeoff is billing: AWS's own on-demand pricing model charges a strongly consistent read one full read request unit per 4 KB, versus half that for an eventually consistent read of the same item — strongly consistent reads cost twice as much, full stop (Amazon DynamoDB: On-Demand pricing).

Firestore doesn't need any of this. Google Cloud's own documentation on how Firestore behaves at scale confirms that Firestore reads are strongly consistent by default — a read returns the latest committed data with no opt-in flag and no capacity penalty for asking (Google Cloud: Understand real-time queries at scale). That's one less thing the Firestore driver has to work around, and one less line item to think about as read volume grows.

Setting each one up

Firestore needs only a project ID — the database segment defaults to (default):

export OPENCONTEXT_DB_URL="firestore://my-gcp-project"
npm i @google-cloud/firestore

DynamoDB's connection string carries a region and a table name instead — open-context also accepts ddb:// as a shorthand alias for the same scheme:

export OPENCONTEXT_DB_URL="dynamodb://us-east-1/opencontext"
npm i @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb

Both drivers are optional peer dependencies — like every one of open-context's 15 backends — so nothing gets installed until you actually pick that scheme. DynamoDB falls back to the default AWS credential provider chain, but if you need to point at a specific role or a local DynamoDB-compatible endpoint for testing, the connection string accepts endpoint, accessKeyId, secretAccessKey, and sessionToken as query parameters.

What's identical no matter which you pick

The reason this choice is low-stakes is the same reason covered in choosing between SQLite and Postgres: every backend, Firestore and DynamoDB included, is validated against the same roughly 50-test conformance suite. Ordering is createdAt ascending then id ascending on every list method, identically, on every backend. An unset bubbleId or description comes back undefined, never null — DynamoDB needs removeUndefinedValues: true configured explicitly on its marshaller to honor that, which is exactly the kind of backend-specific detail the shared driver interface exists to absorb.

Search is the one place both backends pay the same real cost, the tradeoff also covered in Redis vs. MongoDB for an MCP store: neither has a portable case-insensitive substring predicate, so recall_context and search_contexts read the entire context collection and filter it in memory. Results come back identical to a SQL backend — the conformance suite makes sure of that — but on a very large store, a SQL backend that pushes the filter into the database will simply be faster at it.

Which one to choose

FirestoreDynamoDB
CloudGoogle CloudAWS
CredentialsApplication Default Credentials chainDefault AWS credential chain, or DSN params
Setup before first writeNone — collections are created implicitlyNone — a PAY_PER_REQUEST table is created automatically
Read consistencyStrongly consistent by defaultEventually consistent by default; open-context forces strong reads
Cost of read-your-writesNone — it's the default2x the read capacity of an eventually consistent read
Connection stringfirestore://my-projectdynamodb://us-east-1/opencontext

If you're already running other infrastructure on one of these clouds, that's usually the deciding factor — one fewer credential chain and IAM policy to manage. Absent that, Firestore's default strong consistency makes it the simpler mental model for a context store that a single MCP client reads right after it writes, which is the exact pattern save_context followed by recall_context produces on every save.

Point your MCP context store at Firestore or DynamoDB in one environment variable.

Get started with open-context →

FAQ

Does open-context support both Firestore and DynamoDB for the MCP context store?

Yes. Both are two of 15 supported backends, wired up through OPENCONTEXT_DB_URL. Firestore needs the @google-cloud/firestore peer dependency; DynamoDB needs @aws-sdk/client-dynamodb and @aws-sdk/lib-dynamodb. Neither is installed until you actually pick that backend.

Why does DynamoDB cost more per read than Firestore for the same context store?

It doesn't have to — the extra cost comes specifically from open-context forcing strongly consistent reads on DynamoDB, to guarantee getContext sees a context immediately after saveContext. AWS's own pricing model charges a strongly consistent read twice the capacity of an eventually consistent one. Firestore reads are strongly consistent by default, so this cost doesn't apply there.

Do I need to create a DynamoDB table or Firestore database before connecting?

No for either. open-context's DynamoDB driver creates a PAY_PER_REQUEST table automatically on first connect if one doesn't already exist, then waits for it to become active. Firestore collections and documents are created implicitly the first time a context is written, so nothing needs to be provisioned up front.

Which credentials does each backend need?

Firestore reads Google's Application Default Credentials chain, the same one every Google Cloud client library uses, so nothing sensitive goes in the connection string. DynamoDB uses the default AWS credential provider chain, or you can pass accessKeyId, secretAccessKey, and an optional sessionToken as parameters on the dynamodb:// connection string.

Is search slower on Firestore or DynamoDB than on a SQL backend?

For large stores, yes. Neither has a portable case-insensitive substring predicate, so open-context reads the whole context collection and filters in memory, the same approach used for Redis and MongoDB. Every backend passes the same conformance suite and returns identical results, but SQL backends like Postgres and SQLite push that filtering into the database instead, which is faster once you have a very large number of saved contexts.