RocksDB-Sharp

Opening a database

A RocksDB database is a directory on disk that contains SST files, the WAL, the manifest, and the OPTIONS file. To get a handle to it you call one of the static RocksDb.Open* methods with a DbOptions instance and a path.

using RocksDbSharp;

var options = new DbOptions().SetCreateIfMissing(true);
using var db = RocksDb.Open(options, "/var/lib/myapp/state");

Always wrap the returned RocksDb in using so the handle is released and pending writes are flushed.


The five open modes

RocksDB-Sharp exposes every open mode the engine supports. Pick the one that matches the lifecycle you need.

Mode Method Use it for
Read-write (primary) RocksDb.Open(options, path) The default. One process at a time.
Read-only RocksDb.OpenReadOnly(options, path, errorIfLogFileExists) Multiple concurrent readers of a static DB.
Secondary RocksDb.OpenAsSecondary(options, path, secondaryPath) Live follower of a primary, can TryCatchUpWithPrimary().
TTL RocksDb.OpenWithTtl(options, path, ttlSeconds) Keys auto-expire after ttlSeconds.
With column families RocksDb.Open(options, path, columnFamilies) and variants DBs that use multiple column families.

The read-only and secondary modes are documented in detail on the upstream Read-only and Secondary instances wiki page. TTL semantics are on the Time-to-Live wiki page.


Primary (read-write)

The everyday case. Exactly one process can hold the lock at a time — RocksDB throws if a second process tries to open the same directory.

var options = new DbOptions()
    .SetCreateIfMissing(true)
    .SetCreateMissingColumnFamilies(true)
    .IncreaseParallelism(Environment.ProcessorCount);

using var db = RocksDb.Open(options, "/var/lib/myapp/state");

See all DbOptions


Read-only

Open the database without taking the lock. Useful for ad-hoc inspection, sidecar tools, or fanning out queries to multiple processes.

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

string v = db.Get("hello");

errorIfLogFileExists: true makes the open fail if the WAL has unflushed entries — a safety net when you want a guaranteed-clean view.


Secondary (live follower)

A secondary instance attaches to a primary's directory in read-only mode but can be brought up to date by calling TryCatchUpWithPrimary(). Each secondary needs its own secondaryPath for tail-state.

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

// Periodically re-sync with the primary
follower.TryCatchUpWithPrimary();

string v = follower.Get("hello");

For an end-to-end example using WAL streaming for sub-second replication, see the Replication guide.


TTL database

Keys older than ttlSeconds are eligible for compaction-time deletion. TTL is not an exact-expiry mechanism — it kicks in during compaction.

using var db = RocksDb.OpenWithTtl(
    new DbOptions().SetCreateIfMissing(true),
    "/var/lib/myapp/cache",
    ttlSeconds: 60 * 60 * 24); // one day

See the TTL database guide for caveats.


With column families

If the database uses column families (anything beyond "default"), every Open call must enumerate them up front.

var cfs = new ColumnFamilies
{
    { "users",  new ColumnFamilyOptions() },
    { "orders", new ColumnFamilyOptions() },
};

using var db = RocksDb.Open(
    new DbOptions().SetCreateIfMissing(true).SetCreateMissingColumnFamilies(true),
    "/var/lib/myapp/state",
    cfs);

var users  = db.GetColumnFamily("users");
var orders = db.GetColumnFamily("orders");

db.Put("u:42", "Ada", users);

The full guide is on the Column Families page. Upstream reference: Column Families wiki.


Listing column families before opening

If you don't know which column families exist, ask:

foreach (var name in RocksDb.ListColumnFamilies(new DbOptions(), path))
{
    Console.WriteLine(name);
}

// Non-throwing variant
if (RocksDb.TryListColumnFamilies(new DbOptions(), path, out var names))
{
    foreach (var n in names) Console.WriteLine(n);
}

Cleaning up

RocksDb implements IDisposable. Disposing it:

  1. Releases every cached ColumnFamilyHandle.
  2. Calls rocksdb_close, which flushes the MemTable and closes the WAL.
  3. Suppresses finalization so the unmanaged handle can't be double-freed.
using (var db = RocksDb.Open(options, path))
{
    // …
}   // Dispose runs here.

If you can't use using (e.g. the DB outlives a single scope), call db.Dispose() explicitly during application shutdown.

Don't share `RocksDb` across processes

The directory is locked by the primary instance. Use secondary instances for multi-process read access, not multiple primaries.


Inspecting an open database

A few useful properties / methods once you have a RocksDb:

db.Path;                        // the data directory
db.WalPath;                     // configured WAL dir (if any)
db.LogPath;                     // configured info-log dir (if any)

db.GetProperty("rocksdb.stats");                // human-readable stats
db.GetProperty("rocksdb.estimate-num-keys");    // est. key count
db.GetProperty("rocksdb.estimate-pending-compaction-bytes");

db.GetLatestSequenceNumber();   // current sequence number
db.GetLiveFileNames();          // active SST files
db.GetLiveFilesMetadata();      // full metadata for each

The full set of property names is documented on the Property reference wiki page.

Referenced by

© 2026 RocksDB-Sharp. All rights reserved.