RocksDB-Sharp

TTL database

RocksDb.OpenWithTtl opens a database where every key carries an implicit time-to-live. Once a key is older than ttlSeconds, compaction is allowed to drop it. TTL is not exact-expiry — keys are eligible for removal but only actually vanish during the next compaction that touches their SST file.

Upstream reference: Time-to-Live wiki.


Opening a TTL database

var options = new DbOptions().SetCreateIfMissing(true);

using var db = RocksDb.OpenWithTtl(
    options,
    path,
    ttlSeconds: 60 * 60 * 24);   // 1 day

After this, every Put records a timestamp alongside the value. Compaction filters keys whose timestamp is older than ttlSeconds.


Semantics

  • TTL is per-database, not per-key. All keys share the same TTL.
  • Reads of expired keys may still succeed until compaction removes them. If you need strict expiry, layer your own timestamp on the value and check at read time.
  • Compaction does the work. A key that never sees compaction stays around forever. For caches you usually want background compaction enabled (the default).
  • TTL counts from Put time. Updating a key resets its TTL.

Typical use cases

Pattern Why TTL fits
HTTP / RPC response cache Stale entries fall out without manual eviction.
Idempotency keys Forget request IDs older than the retry window.
Rate-limit buckets Counters that auto-purge after their window.
Short-lived dedupe set Drop "seen" markers once the dedupe horizon passes.

When TTL is the wrong tool

  • You need exact expiry. TTL is compaction-driven; expired keys may be readable for a while.
  • You need per-key TTLs. Use a value-side timestamp and a periodic sweep.
  • You mix TTL and non-TTL data. Use column families — one CF with TTL on a OpenWithTtl-style configuration won't help, but you can manage expiry yourself per CF.

Worked example: caching layer

public sealed class TtlCache : IDisposable
{
    private readonly RocksDb _db;

    public TtlCache(string path, TimeSpan ttl)
    {
        var options = new DbOptions()
            .SetCreateIfMissing(true)
            .IncreaseParallelism(Environment.ProcessorCount);

        _db = RocksDb.OpenWithTtl(options, path, (int)ttl.TotalSeconds);
    }

    public void Set(string key, string value) => _db.Put(key, value);
    public string? Get(string key)            => _db.Get(key);

    public void Dispose() => _db.Dispose();
}
using var cache = new TtlCache("/tmp/cache", TimeSpan.FromHours(1));
cache.Set("response:42", "...");

Referenced by

© 2026 RocksDB-Sharp. All rights reserved.