NativeLink

MongoDB

Back the cache with MongoDB: collections, write concern, timeouts, and what the change-streams flag is for.

Who this is for: anyone who already operates MongoDB. What you'll have at the end: a Mongo-backed CAS behind a local fast tier. Time: twenty-five minutes.

Before you start

A config file you can edit (see Configuration), and a reachable MongoDB deployment.

Mongo lands between Redis and object storage: durable, shared across machines, single-digit milliseconds away, and priced by the cluster you run rather than per gigabyte stored. Storage backends compares all of them on the same axes.

The recipe

stores: [
  {
    name: "CAS_MAIN_STORE",
    fast_slow: {
      fast: {
        memory: {
          eviction_policy: { max_bytes: "1gb" },
        },
      },
      slow: {
        experimental_mongo: {
          connection_string: "${MONGO_URI}",
          database: "nativelink",
          cas_collection: "cas",
          key_prefix: "prod:",
        },
      },
    },
  },
],

connection_string is the only required field and takes either form Mongo accepts, mongodb://localhost:27017 or mongodb+srv://cluster.mongodb.net for Atlas. It carries the credentials, so keep it in the environment and reference it with ${VAR}; see The config file.

Everything else has a default: database is nativelink, cas_collection is cas, scheduler_collection is scheduler, and key_prefix is empty.

ExperimentalMongoSpec

Change streams and the scheduler

The Mongo store implements the scheduler-store interface, and enable_change_streams: true is what that interface needs: the store refuses to hand out scheduler subscriptions without it. In v1.6.5, though, the simple scheduler's experimental_backend accepts only memory and redis, so there is no config path that puts a Mongo store behind the scheduler. Treat this store as a CAS and Action Cache backend, and see Redis for a shared scheduler.

ExperimentalSimpleSchedulerBackend

Leave enable_change_streams off for a store used as a CAS. It buys nothing there.

Options worth setting

FieldDefaultWhat it decides
databasenativelinkDatabase name
cas_collectioncasCollection holding CAS objects
scheduler_collectionschedulerCollection holding scheduler state
key_prefixemptyNamespacing when several deployments share one database
read_chunk_size64 KBBytes pulled per chunk when streaming a blob out
max_requestsunlimitedCeiling on concurrent requests to the deployment
connection_timeout_ms3000Applied as both the driver's connect timeout and its server-selection timeout
command_timeout_ms10000Accepted and defaulted, but not applied to any driver option in v1.6.5
enable_change_streamsfalseRequired for scheduler subscriptions, which nothing uses yet (see above)

Write concern is exposed as three separate fields mirroring Mongo's own: write_concern_w (a number like 1, or the string "majority"), write_concern_j (whether to wait for the journal), and write_concern_timeout_ms. All three are optional and unset means the deployment's own default applies, but write_concern_j or write_concern_timeout_ms without write_concern_w is rejected at startup. For a CAS, "majority" is the honest setting, because a cache entry acknowledged by one node and then lost to a failover is a cache entry a client believes exists.

max_requests is the equivalent of Redis's permit ceiling and is unlimited by default. Set it if bursts are overwhelming the deployment; queuing in NativeLink beats timing out at Mongo. Zero is rejected at startup.

ExperimentalMongoStore::new

`max_concurrent_uploads` is deprecated and unused

It survives in the schema for compatibility. Setting it only logs a warning; use max_requests to bound concurrency.

Steps

  1. Provision the deployment: a replica set if you want writes to survive a failover with "majority" write concern.

  2. Create a user with read and write on the database, and put the full connection string in the environment rather than the config file.

  3. Add the store, choosing a key_prefix if this database is shared with another NativeLink deployment.

  4. Set write concern to "majority" for anything you intend to trust.

  5. Run a build twice, the second time from a different machine, to confirm the store is genuinely shared.

You did it right if

  • Documents appear in the CAS collection during the first build.
  • A second machine pointed at the same deployment gets cache hits for objects the first one uploaded.
  • No connection or server-selection timeouts in the logs at your normal peak load.

When it doesn't work

NextCompose stores

Putting a local fast tier in front of this one, and the rest of the composition vocabulary.

SidewaysRedis

The backend that can hold scheduler state in v1.6.5, if you need several schedulers to share one queue.

On this page