MCPcopy Index your code
hub / github.com/NoKV-Lab/NoKV

github.com/NoKV-Lab/NoKV @v0.9.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.9.0 ↗ · + Follow
14,402 symbols 64,282 edges 847 files 2,728 documented · 19%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

NoKV

<strong>An open-source namespace metadata substrate for distributed filesystems, object storage, and AI dataset metadata.</strong>







<a href="https://github.com/feichai0017/NoKV/actions"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/feichai0017/NoKV/go.yml?branch=main" /></a>
<a href="https://codecov.io/gh/feichai0017/NoKV"><img alt="Coverage" src="https://img.shields.io/codecov/c/gh/feichai0017/NoKV" /></a>
<a href="https://goreportcard.com/report/github.com/feichai0017/NoKV"><img alt="Go Report Card" src="https://img.shields.io/badge/go%20report-A+-brightgreen" /></a>
<a href="https://pkg.go.dev/github.com/feichai0017/NoKV"><img alt="Go Reference" src="https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white" /></a>
<a href="https://github.com/avelino/awesome-go#databases-implemented-in-go"><img alt="Mentioned in Awesome" src="https://awesome.re/mentioned-badge.svg" /></a>
<a href="https://landscape.cncf.io/?group=projects-and-products&item=runtime--cloud-native-storage--nokv"><img alt="CNCF Landscape" src="https://img.shields.io/badge/CNCF%20Landscape-listed-5699C6?logo=cncf&logoColor=white" /></a>







<img alt="Go Version" src="https://img.shields.io/badge/go-1.26%2B-00ADD8?logo=go&logoColor=white" />
<img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-yellow" />
<a href="https://deepwiki.com/feichai0017/NoKV"><img alt="DeepWiki" src="https://img.shields.io/badge/DeepWiki-Ask-6f42c1" /></a>

What is NoKV?

NoKV is the metadata substrate that filesystems, object storage, and AI dataset layers shouldn't have to build themselves.

Meta Tectonic uses ZippyDB. Google Colossus uses Spanner. DeepSeek 3FS uses FoundationDB. Each big-tech system extracted a separate metadata layer from its data layer — because grafting namespace semantics onto a generic KV is the part that breaks under scale.

NoKV is that layer, open-sourced and namespace-native: server-side ReadDirPlus / WatchSubtree / SnapshotSubtree / RenameSubtree, formally-verified authority handoff, sub-second prefix-scoped change feeds. You bring the data plane (FUSE driver, S3 frontend, dataset SDK); NoKV owns namespace truth.

Where it sits: NoKV is the layer above generic KV (FoundationDB / TiKV / etcd) and below filesystem-shaped consumers (CephFS / JuiceFS / S3 gateways / AI training pipelines). Apache-2.0.

Why namespace metadata is its own layer, not a feature you bolt onto generic KV:

  1. Server-side namespace primitives. ReadDirPlus returns one directory + N child stats in one round-trip; client-side stitching on a generic KV does 1+N round-trips with a 42× end-to-end latency penalty (measured on the same NoKV cluster — see Headline Evidence). WatchSubtree ships a prefix-scoped change feed at 178 ms p50, vs. client-side prefix scans on key-range watches.

  2. Namespace correctness is its own class. Subtree authority handoff, mount lifecycle, snapshot epoch, and quota fence have a formal correctness model that generic KV doesn't speak. NoKV's Eunomia protocol is TLC-model-checked under finite bounds for handoff legality — a property no general-purpose KV provides because it isn't a general-purpose KV property.

  3. Bring your own data plane. NoKV does not store object bytes, chunk data, or POSIX file content. You wire it under a FUSE driver, an S3 gateway, or a dataset SDK; NoKV is the namespace truth those frontends consume. This is the layer split Meta / Google / DeepSeek already chose internally — extracted, packaged, and Apache-2.0.

Three audiences that all sit on the same substrate:

  • 🗂️ Distributed filesystems — DFS frontends (FUSE / NFS / SMB drivers, JuiceFS / CubeFS-style services) consume fsmeta for inode / dentry / mount / subtree authority instead of writing their own metadata layer on top of Redis / TiKV / FoundationDB
  • 🪣 Object storage namespace layers — S3-compatible gateways consume the same fsmeta for bucket / prefix / version metadata, getting fast LIST (server-side ReadDirPlus) and prefix-scoped event streams without client-side stitching
  • 🧪 AI dataset and agent workspace metadata — checkpoint storms (atomic multi-key AssertionNotExist), point-in-time namespace reads (SnapshotSubtree; long-lived retention is a GC boundary), prefix-scoped change feeds for training pipelines and shared agent workspaces (WatchSubtree) — without retrofitting them onto a generic KV

NoKV does for namespace metadata what etcd did for cluster state: a purpose-built coordination layer instead of forcing engineers to re-derive namespace semantics on every project.

📬 Contact Us

We are looking for design partners, contributors, and research collaborators working on distributed filesystems, object-storage namespace layers, AI dataset infrastructure, or agent workspace metadata.

📊 Headline Evidence

Underlying KV layer (YCSB single-node, NoKV vs Badger / Pebble)

Apple M3 Pro · records=1M · ops=1M · value_size=1000 · conc=16

Workload Description NoKV Badger Pebble
YCSB-A 50/50 read/update 175,905 108,232 169,792
YCSB-B 95/5 read/update 525,631 188,893 137,483
YCSB-C 100% read 409,136 242,463 90,474
YCSB-D 95% read, 5% insert (latest) 632,031 284,205 198,139
YCSB-E 95% scan, 5% insert 45,620 15,027 40,793
YCSB-F read-modify-write 157,732 84,601 122,192

Units: ops/sec. Full latency in benchmark/README.md. Single-node localhost, not multi-host production.

🧭 Why NoKV vs X?

If you need… You should probably use… Where NoKV fits
A complete distributed filesystem (FUSE-mountable, full POSIX) CephFS, JuiceFS NoKV is not an FS — but JuiceFS-style systems default to Redis / TiKV for their metadata backend, which breaks at scale. NoKV can be JuiceFS's metadata backend.
A production object store MinIO, Ceph RGW NoKV is not an object store — object body I/O isn't its job. NoKV provides the namespace layer above the object backend (bucket / prefix / version)
A custom metadata service you're writing on top of FoundationDB / TiKV / etcd NoKV This is exactly what NoKV replaces. ReadDirPlus / WatchSubtree / SnapshotSubtree are server-side primitives — you don't have to stitch them client-side. Apache-2.0.
A production distributed KV TiKV, FoundationDB, CockroachDB NoKV does not compete with them — they own the generic-KV market. NoKV is a metadata-native layer that can run on top of them (or, today, on its own engine)
Production distributed SQL CockroachDB, TiDB Different scope (relational, not namespace)
Just an embedded LSM Pebble, Badger NoKV's engine is not a drop-in library
A Raft library etcd/raft, dragonboat NoKV's raftstore (per-region runtime, transport, membership, snapshot install, apply observer) is built on top of etcd/raft RawNode. Owned: the integration. Reused: the consensus algorithm.

NoKV's value comes from being metadata-native, not generic-KV-with-metadata-glued-on. The same architectural slice big-tech filesystems already extract internally — ReadDirPlus, prefix-scoped event streams, formally-verified authority handoff — packaged as a layer you can drop in instead of writing yourself.

🏗️ Architecture

NoKV Architecture

🗂️ fsmeta — Namespace Metadata Service

Native API surface (gRPC at nokv-fsmeta:8090, also embedded Go via fsmeta/runtime/raftstore.Open):

Primitive Semantics
ReadDirPlus Fused directory scan + batch inode fetch under one snapshot, avoiding client-side N+1 metadata reads
WatchSubtree Prefix-scoped live change feed with ready signal, cursor replay, and flow-control acks
SnapshotSubtree MVCC read-version token for point-in-time dataset / bucket / directory reads; long-lived retention is a GC-layer boundary
RenameSubtree Cross-region atomic namespace move backed by Percolator 2PC
Basic namespace ops Create, Lookup, ReadDir, Link, Unlink, quota usage, and mount lifecycle

Authority lifecycle (rooted in meta/root, managed via nokv mount / nokv quota CLI):

Domain Rooted truth Runtime view
Mount MountRegistered / MountRetired (auto-declares era=0 SubtreeAuthority) Mount admission cache
Subtree authority SubtreeAuthorityDeclared / SubtreeHandoffStarted / SubtreeHandoffCompleted RenameSubtree era frontier
Snapshot epoch SnapshotEpochPublished / SnapshotEpochRetired Read-version cache
Quota fence QuotaFenceUpdated (mount + subtree level, bytes + inodes) Usage in raftstore (transactional, not in-memory)

Documentation: docs/guide/fsmeta.md

🚦 Quick Start

Run a full cluster

# Local processes — meta-root + coordinator + 3-store cluster + fsmeta gateway
./scripts/dev/cluster.sh --config ./raft_config.example.json

# Or: Docker Compose (cluster + fsmeta gateway, with mount-init bootstrap)
docker compose up -d

# Local Docker development build
docker compose up -d --build

# Return to the published image after a local build when available
make docker-up

Use fsmeta from Go (embedded — same Executor as the gRPC server)

package main

import (
    "context"

    "github.com/feichai0017/NoKV/fsmeta"
    fsmetaraftstore "github.com/feichai0017/NoKV/fsmeta/runtime/raftstore"
)

func main() {
    ctx := context.Background()
    rt, err := fsmetaraftstore.Open(ctx, fsmetaraftstore.Options{
        CoordinatorAddr: "127.0.0.1:2379",
    })
    if err != nil {
        panic(err)
    }
    defer rt.Close()

    // mount must be registered first (see `nokv mount register`)
    _, err = rt.Executor.Create(ctx, fsmeta.CreateRequest{
        Mount:  "default",
        Parent: 1,
        Name:   "hello.txt",
        Attrs: fsmeta.CreateAttrs{
            Type: fsmeta.InodeTypeFile,
            Size: 13,
        },
    })
    if err != nil {
        panic(err)
    }

    page, _ := rt.Executor.ReadDirPlus(ctx, fsmeta.ReadDirRequest{
        Mount: "default", Parent: 1, Limit: 100,
    })
    for _, e := range page {
        println(e.Dentry.Name, e.Inode.Size)
    }
}

Use fsmeta from any language (gRPC)

# Bootstrap a mount (required before first write)
nokv mount register --coordinator-addr 127.0.0.1:2379 \
  --mount default --root-inode 1 --schema-version 1

# Set a quota fence (mount-level)
nokv quota set --coordinator-addr 127.0.0.1:2379 \
  --mount default --limit-bytes 1073741824 --limit-inodes 1000000

# Run the standalone fsmeta gRPC gateway with metrics
nokv-fsmeta --addr 127.0.0.1:8090 --coordinator-addr 127.0.0.1:2379 \
  --metrics-addr 127.0.0.1:9101

Then use any gRPC client against fsmeta.proto (Go typed client at fsmeta/client/).

Inspect runtime state

# Live, via expvar (executor / watch / quota / mount / session metrics)
curl http://127.0.0.1:9101/debug/vars | jq '.nokv_fsmeta_executor, .nokv_fsmeta_watch, .nokv_fsmeta_quota, .nokv_fsmeta_mount, .nokv_fsmeta_sessions'

# Offline forensics from a stopped node's workdir
nokv stats --workdir ./artifacts/cluster/store-1
nokv manifest --workdir ./artifacts/cluster/store-1
nokv regions --workdir ./artifacts/cluster/store-1 --json

Full guide: docs/guide/getting_started.md · CLI reference: docs/guide/cli.md

🧩 Modules

Module Responsibility Docs
fsmeta/ Namespace metadata schema, executor, gRPC service, embedded API fsmeta
fsmeta/exec/watch/ WatchSubtree router + RemoteSource + catch-up replay fsmeta
meta/root/ Typed rooted truth kernel (Delos-lite) Rooted Truth
coordinator/ Routing, TSO, store discovery, root-event publish, streaming subscribe Coordinator
raftstore/ Multi-Raft, transport, membership, SST snapshot install, apply observer RaftStore
txn/percolator/ Distributed MVCC 2PC + AssertionNotExist Percolator
local/ Embedded single-node DB facade, local stats, workdir mode, and local-only write runtime internals Runtime
engine/lsm/ MemTable, flush, leveled compaction, SST LSM · flush · compaction
engine/wal/ WAL segments, CRC, rotation, replay WAL
engine/slab/ Append-only mmap segment substrate for derived sidecar caches VFS
engine/manifest/ VersionEdit log, atomic CURRENT Manifest
engine/vfs/ VFS abstraction, FaultFS, cross-platform atomic rename VFS
thermos/ Hot-key observer [Thermos](docs/guide/t

Extension points exported contracts — how you extend this code

RegionResolver (Interface)
RegionResolver resolves Region metadata for an arbitrary key. A Coordinator client implementation should satisfy this in [9 …
raftstore/client/client.go
Registration (Interface)
Registration unregisters a previously registered observer. Calling Close more than once is a no-op. [105 implementers]
raftstore/store/observer/observer.go
StagedPublishClient (Interface)
StagedPublishClient is the narrow namespace surface needed for staged publish. GRPCClient satisfies it. [12 implementers]
fsmeta/client/staged_publish.go
AtomicMutateOnePhase (Interface)
AtomicMutateOnePhase is an optional TxnRunner extension. handled=false means the runner could not keep the mutation in o [7 …
fsmeta/exec/executor.go
StoreLister (Interface)
StoreLister returns the runtime store registry snapshot. [6 implementers]
fsmeta/runtime/raftstore/remote_watch.go
TableRef (Interface)
TableRef is the minimal contract a table must satisfy to be cached: ref- counting only. The cache never reads the table' [7 …
engine/lsm/cache/cache.go
Iterator (Interface)
Iterator abstracts key/value iteration. [11 implementers]
engine/index/iterator.go
Store (Interface)
Store is the narrow internal storage surface used by Percolator and raftstore MVCC maintenance code. [7 implementers]
txn/storage/store.go

Core symbols most depended-on inside this repo

Equal
called by 3822
thermos/node.go
Lock
called by 659
engine/vfs/vfs.go
Equal
called by 602
meta/topology/types.go
Load
called by 505
coordinator/rootview/root.go
Add
called by 503
engine/lsm/memtable.go
Error
called by 377
errors/errors.go
Close
called by 357
engine/index/iterator.go
Close
called by 308
raftstore/client/client.go

Shape

Method 7,014
Function 5,618
Struct 1,420
TypeAlias 165
Interface 150
FuncType 35

Languages

Go100%

Modules by API surface

pb/meta/root.pb.go785 symbols
pb/kv/kv.pb.go664 symbols
pb/coordinator/coordinator.pb.go558 symbols
pb/fsmeta/fsmeta.pb.go444 symbols
pb/admin/admin.pb.go216 symbols
pb/raft/cmd.pb.go162 symbols
coordinator/server/service_test.go131 symbols
txn/percolator/txn_test.go113 symbols
pb/meta/recovery.pb.go113 symbols
pb/coordinator/coordinator_grpc.pb.go109 symbols
coordinator/client/client.go104 symbols
meta/wire/root.go102 symbols

For agents

$ claude mcp add NoKV \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact