DEV Community

puffball1567
puffball1567

Posted on • Edited on

Hello, KoutenDB! A Nim Database Built Around Data Locality

Hello! I am building KoutenDB, an open-source NoSQL document and vector
store written in Nim.

The project starts with a simple question:

What if a database could avoid opening unrelated data before expensive
retrieval and application processing begin?

Modern systems accumulate documents, tenant data, application state, embeddings,
logs, and knowledge bases. A request can spend significant resources on data
that is not ultimately useful: reading it, transferring it, holding it in
memory, reranking it, summarizing it, or passing it into an LLM context.

KoutenDB is my attempt to make an application's natural data locality part of
the storage and retrieval model.

The central idea: a ring

KoutenDB uses a ring as a semantic and structural placement unit.

An application or import rule chooses a ring when writing data. That same ring
can then define the initial scope of a read.

docs/japan/support
tenant/acme/orders/2026
users/123/profile
Enter fullscreen mode Exit fullscreen mode

These are not merely directory-like names. They are coordinates in the
retrieval space. Records placed in the same ring are expected to be useful
neighbors for retrieval.

That makes a ring different from an ordinary collection label. It says both:

  • where a record belongs; and
  • which local region should be opened first for a request.

A ring is not a B+ tree

KoutenDB rings are not intended to replace B+ trees.

A B+ tree organizes data by ordered keys. It is excellent for primary-key
reads, secondary-index lookups, time ranges, sorted pagination, and other
queries that can be expressed as a key lookup or key range scan.

A B+ tree answers:

Where is this key or key range?

A KoutenDB ring answers:

Which local region of the data should be opened first in this context?

They optimize different parts of a system. A B+ tree makes ordered key access
efficient. A ring tries to reduce the semantic candidate set before more
expensive downstream work begins.

Why orbital mechanics?

The naming and part of the model are inspired by orbital mechanics.

In an orbital system, a body's position can be estimated from compact orbital
elements such as period, phase or epoch, eccentricity, and semi-major axis.
KoutenDB uses that as an engineering abstraction.

A ring is like a semantic data orbit. Records in a ring inherit lightweight
orbital metadata, including values such as a period and headAngle. This lets a
ring act as both a placement unit and a small part of the query plan.

The celestial-mechanics vocabulary—rings, orbits, encounters, and
accretion—is not the value proposition. KoutenDB is not a physics simulator.

The useful idea is that placement, movement, proximity, and retrieval scope can
be explicit and observable, rather than hidden behind a central directory or
reconstructed for every request.


The short version: KoutenDB uses application-level locality to reduce the
candidate set before expensive retrieval, reranking, memory use, network
transfer, or LLM context construction begins.

A small example

Here is what ring placement looks like from Nim:

import koutendb

var db = koutendb.open(dataDir = "data")

db.setRingDescription(
  "docs/japan",
  "Japanese product documentation and support articles"
)

discard db.put(
  """{"slug":"refund","title":"Refund guide"}""",
  ring = "docs/japan"
)

discard db.put(
  """{"slug":"setup","title":"Setup guide"}""",
  ring = "docs/japan"
)
Enter fullscreen mode Exit fullscreen mode

If the application already knows that it needs Japanese documentation, it can
start with that ring:

for item in db.listByRing("docs/japan"):
  echo item.payload
Enter fullscreen mode Exit fullscreen mode

The same idea applies to vector retrieval:

let query = @[1.0'f32, 0.0'f32]

let hits = db.retrieve(
  query,
  ring = "docs/japan",
  budget = 3
)

for hit in hits:
  echo hit.payload
Enter fullscreen mode Exit fullscreen mode

The important detail is that docs/japan is not a label added after the
retrieval. It is a placement decision at write time and an initial scope for
reads.

Applications are still responsible for designing useful rings. But many already
know meaningful locality: tenant, region, product area, document domain, user,
or time range. KoutenDB is an attempt to let the database use that information
directly.

Why this matters for AI, RAG, and web systems

For transactional workloads, an efficient indexed lookup is often enough.

For retrieval-heavy workloads, finding one row is not always the expensive
part. The larger cost can be dealing with a wide set of semantically weak
candidates after the lookup.

This is particularly relevant to AI and RAG systems. A database may efficiently
retrieve a key range, but the result can still contain many weak candidates.
Those candidates may then be embedded, reranked, summarized, kept in memory,
or sent to an LLM.

KoutenDB tries to reduce that candidate set earlier.

When ring placement reflects useful locality, the expected benefits are:

  • fewer records to rank;
  • fewer payloads held in memory;
  • fewer bytes transferred between services;
  • fewer tokens passed to downstream LLMs;
  • clearer boundaries for tenants, regions, backups, migrations, and authorization.

What the early numbers show

The current benchmarks do not claim that KoutenDB is universally faster than
every B+ tree-based database.

They test a narrower hypothesis: when ring placement captures useful locality,
can KoutenDB reduce the working set and downstream candidate volume while
keeping the read path lightweight?


Working-set benchmark

With 100 rings and 10,000 documents, the number of records scanned per query
decreased from 10,000 to 100: a 99% reduction in the candidate working
set.


Memory-pressure benchmark

With 100 rings, 100,000 documents, and 512-byte payloads, candidate memory per
query decreased from 93.079 MiB to 0.931 MiB: also a 99% reduction.


RAG-oriented cases

In a fixed-quality synthetic RAG case, records scanned decreased from
8,000 to 1,000 and tokens per query from 3960 to 657.8.

In a 400-document, 6-ring AI/RAG case study, records scanned decreased from
400 to 40, while tokens per query decreased from 615.2 to 231.6 with
recall remaining 1.000.

These are early, reproducible results rather than universal performance claims.
They depend on ring placement expressing useful locality. The benchmark scripts,
their conditions, and their limitations are in the project repository.

Source code, documentation, benchmark scripts, and issue tracking are available
at github.com/puffball1567/koutendb.

A longer-term hope

The immediate goal is practical: reduce unnecessary candidate data before
expensive downstream processing.

If that can also contribute over time to lower token consumption in AI and RAG
systems, less energy spent on unnecessary reads and computation, and less
pressure to continually expand memory, storage, and compute hardware capacity,
that would be a meaningful result.

KoutenDB alone will not directly solve token, energy, or semiconductor demand.
But avoiding unnecessary data movement seems like a useful place to start.

Current boundaries

KoutenDB is not a replacement for every database or every B+ tree use case.

It is most interesting when an application already has meaningful locality:
tenants, users, regions, topics, document groups, time partitions,
prompt/context stores, or RAG document collections.

It is currently a technical preview. I am not presenting it as a production
replacement for PostgreSQL, Redis, MongoDB, or dedicated vector databases.

KoutenDB provides a Nim API, CLI, server mode, C ABI, and language drivers. In
this series, I plan to write about ring placement, retrieval, cluster behavior,
benchmarks, Nim implementation details, and driver development.

I hope KoutenDB can be useful both as a practical experiment in reducing
unnecessary data movement and as a way to explore what a locality-first
database model can look like.

Feedback, questions, and use cases are very welcome.

Top comments (2)

Collapse
 
mads_hansen_27b33ebfee4c9 profile image
Mads Hansen

The data-locality angle is worth more attention than it usually gets.

A lot of database performance discussions jump straight to indexes, caches, or query syntax. Those matter, but layout often decides whether the system is working with the hardware or asking it to fight back.

A few questions I’d be curious about for RocheDB:

  • how records are grouped on disk
  • whether locality is optimized for point reads, range scans, or graph-like traversal
  • how compaction affects locality over time
  • what happens when write patterns are less predictable
  • how secondary access paths avoid fighting the primary layout
  • whether locality hints are exposed to users or kept internal

The hard part is usually preserving locality after the first clean benchmark. Real workloads mutate, delete, backfill, and query from odd angles.

Cool direction. Small engines that make a strong bet on layout can teach bigger systems a lot.

Collapse
 
puffball1567 profile image
puffball1567

v0.5.0 added the first concrete locality surface: WAL locality metrics, locality-aware compaction, a CLI locality report, interleaved-write demo, and docs explaining how ring/stellar locality maps to logical and physical layout. It does not claim to solve long-running workload locality yet; that is now measurable and tracked.