RocksDB-Sharp

Read-only and secondary instances

A RocksDB directory is normally exclusively locked by the writing process. Two modes let other processes / instances attach without taking the lock:

Mode Sees writes? Open lock
Read-only No (snapshot at open time) Doesn't take the lock
Secondary Yes, when you call TryCatchUpWithPrimary Doesn't take the lock

Upstream reference: Read-only and Secondary instances.


Read-only

Use this when you want a frozen view, or when several processes only need to read.

using var db = RocksDb.OpenReadOnly(
    new DbOptions(),
    "/var/lib/myapp/state",
    errorIfLogFileExists: false);

string v = db.Get("k");
  • The DB sees the state as of open time. New writes from the primary are invisible.
  • errorIfLogFileExists: true makes the open fail if there are unflushed WAL entries — handy when you want a guarantee that you're seeing a fully flushed snapshot.

You can also open with column families:

using var db = RocksDb.OpenReadOnly(
    new DbOptions(),
    path,
    columnFamilies: cfs,
    errIfLogFileExists: false);

Secondary

A secondary is a live follower. It re-uses the primary's directory in read-only mode and catches up on demand by replaying new WAL/MANIFEST entries.

using var follower = RocksDb.OpenAsSecondary(
    new DbOptions(),
    primaryPath:   "/var/lib/myapp/state",
    secondaryPath: "/var/lib/myapp/follower");   // tail-state dir

// Poll: bring the follower up to date with the primary
follower.TryCatchUpWithPrimary();

string v = follower.Get("hello");
  • secondaryPath is a separate directory the secondary uses for bookkeeping. It does not write into the primary's data dir.
  • Call TryCatchUpWithPrimary() whenever you want fresh data. It's cheap when there's nothing new.
  • The primary should keep its WAL files long enough for secondaries to catch up. See SetWalTtlSeconds and SetWalSizeLimitMB.

For a richer setup that streams the WAL over the network (rather than relying on a shared filesystem), see the Replication guide.


Multiple secondaries

Each secondary needs its own secondaryPath. They can all read the same primary in parallel:

using var sa = RocksDb.OpenAsSecondary(new DbOptions(), primary, "/var/lib/sec-a");
using var sb = RocksDb.OpenAsSecondary(new DbOptions(), primary, "/var/lib/sec-b");

Caveats

No writes

A secondary cannot Put, Merge, Remove, or Write. It's read-only.

Disk visibility

On Linux, a secondary only sees data the primary has actually fsynced. Make sure the primary's WAL retention is long enough that secondaries can keep up.

Catch-up doesn't block writers

TryCatchUpWithPrimary() runs against the on-disk state. It doesn't coordinate with the primary process and doesn't block it.


Read-only vs. secondary at a glance

  • Read-only: lowest overhead, single point-in-time view. Open, read, close.
  • Secondary: nearly the same overhead, but with the ability to keep up with the primary by polling. Good for live dashboards, sidecar query nodes, or zero-downtime takeovers.
  • Checkpoint (Checkpoints guide): an on-disk copy you can open with either of the above on any host.
© 2026 RocksDB-Sharp. All rights reserved.