ByTech.LsmTree 1.1.0

dotnet add package ByTech.LsmTree --version 1.1.0
                    
NuGet\Install-Package ByTech.LsmTree -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ByTech.LsmTree" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ByTech.LsmTree" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="ByTech.LsmTree" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ByTech.LsmTree --version 1.1.0
                    
#r "nuget: ByTech.LsmTree, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ByTech.LsmTree@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ByTech.LsmTree&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=ByTech.LsmTree&version=1.1.0
                    
Install as a Cake Tool

ByTech.LsmTree

A disk-based, persistent Log-Structured Merge-tree for .NET 10 — a write-optimized sorted key-value store with WAL-based durability, leveled compaction, bloom-filter accelerated point lookups, and concurrent reads/writes.

NuGet Downloads .NET Tests License

v1.1.0 — see the CHANGELOG. Originally exported one-time from the ByTech.Bedrock durable-primitives framework.


Features

  • Sorted key-value store — point lookups, range scans, prefix scans, batch mutations
  • Write-optimized — in-memory memtable, write-ahead log (WAL), leveled disk segments, background flush and compaction
  • WAL durability — write-ahead log with replay-on-open crash recovery
  • Configurable durabilityMemoryOnly / WriteBuffered / PeriodicSync / FlushOnCommit / ImmediateSync
  • Bloom filters — accelerated negative point lookups, configurable false-positive rate
  • Block cache — hot-block caching for read-mostly workloads
  • Online compaction — single-flight tiered/leveled strategy
  • Generic keys and values — bring your own ICodec<T>; built-in Utf8StringCodec, JsonCodec<T>, BytePassthroughCodec, plus a CodecPipeline<T> for layering ICodecMiddleware (compression, encryption, …)

Installation

dotnet add package ByTech.LsmTree

Quick start

using ByTech.LsmTree;

var options = new LsmTreeOptions
{
    BaseDirectory   = "./data/mystore",
    DurabilityLevel = DurabilityLevel.PeriodicSync,
};

await using var tree = new LsmTree<string, string?>(
    name:           "mystore",
    keyCodec:       new Utf8StringCodec(),
    valueCodec:     new Utf8StringCodec()!,
    options:        options,
    tombstoneValue: null,
    isTombstone:    v => v is null);

await tree.PutAsync("hello", "world");
var value = await tree.GetAsync("hello");          // "world"

await tree.DeleteAsync("hello");
value = await tree.GetAsync("hello");              // null

Range and prefix scans

// Range scan, inclusive bounds
await foreach (var kv in tree.RangeScanAsync("sku-00100", "sku-00200"))
    Console.WriteLine($"{kv.Key} -> {kv.Value}");

// Prefix scan (requires a prefixMatcher at construction)
await using var tree = new LsmTree<string, string?>(
    "skus", new Utf8StringCodec(), new Utf8StringCodec()!, options,
    tombstoneValue: null, isTombstone: v => v is null,
    prefixMatcher: (k, p) => k.StartsWith(p, StringComparison.Ordinal));

await foreach (var kv in tree.PrefixScanAsync("sku-09"))
    Console.WriteLine($"{kv.Key} -> {kv.Value}");

Batch mutations

await tree.BatchMutateAsync(
[
    new(MutationType.Put,    "sku-01", "alpha"),
    new(MutationType.Put,    "sku-02", "beta"),
    new(MutationType.Delete, "sku-03", null),
]);

Maintenance & introspection

await tree.CheckpointAsync();                 // flush memtable to disk
await tree.CompactAsync();                    // single-flight compaction pass

var integrity = await tree.ValidateIntegrityAsync();
Console.WriteLine($"CRC failures: {integrity.ChecksumFailures}");

var metrics = tree.GetMetrics();
Console.WriteLine($"ops={metrics.TotalOperations}  items={metrics.ItemCount}  compactions={metrics.CompactionCount}");
Console.WriteLine($"block cache: {metrics.BlockCacheHits} hits / {metrics.BlockCacheMisses} misses");
Console.WriteLine($"bloom: {metrics.BloomFilterNegatives}/{metrics.BloomFilterQueries} probes skipped a segment");

Diagnostics

The tree emits System.Diagnostics.ActivitySource spans for read, write-throttle, and compaction events. Attach a listener filtered to source ByTech.LsmTree:

using System.Diagnostics;
using ByTech.LsmTree.Diagnostics;

ActivitySource.AddActivityListener(new ActivityListener
{
    ShouldListenTo = src => src.Name == LsmTelemetry.SourceName,
    Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllData,
    ActivityStarted = a => Console.WriteLine($"start {a.OperationName}"),
});

Available span names are listed as constants on LsmTelemetry (ReadGet, ReadRwLockWait, ReadPathWalk, CompactionSwap, ThrottleWait).

Options reference

Option Default Notes
BaseDirectory (required) Root directory for WAL + segments
DurabilityLevel PeriodicSync When mutations become crash-safe
PeriodicSyncInterval 1 s How often PeriodicSync fsyncs the WAL in the background
MemTableSizeThreshold 64 MB Bytes before active memtable freezes
SparseIndexInterval 128 Every Nth entry pinned to in-memory sparse index
Level0CompactionThreshold 4 L0 segments before triggering L0→L1 compaction
SizeMultiplier 10 Capacity ratio between adjacent levels
MaxLevelCount 5 Max number of LSM levels
EnableBloomFilters true Build bloom filters on disk segments
BloomFilterFalsePositiveRate 0.01 Base FPR (deeper levels use a tighter FPR)
WriteThrottleLevel0Threshold 8 L0 segment count that activates write throttling
BlockCacheMaxSizeBytes 64 MB Block-cache capacity (set to 0 to disable)

Dependencies

  • ByTech.BloomFilter — bloom-filter primitive used by disk-segment readers
  • System.IO.Hashing — checksums on disk segments and WAL records

License

MIT — see LICENSE.MD.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 87 5/14/2026
1.0.0 84 5/13/2026

See CHANGELOG.md. Highlights: all five DurabilityLevel modes now behave as documented; ValidateIntegrityAsync V2-segment false-failure bug fixed; WAL batcher memtable-rotation hang fixed; background flush failures retried with backoff; block-cache and bloom-filter counters exposed via GetMetrics; new PeriodicSyncInterval option.