<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: puffball1567</title>
    <description>The latest articles on DEV Community by puffball1567 (@puffball1567).</description>
    <link>https://dev.to/puffball1567</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4028036%2F318aece8-8f65-4e85-9c32-200838e42224.png</url>
      <title>DEV Community: puffball1567</title>
      <link>https://dev.to/puffball1567</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/puffball1567"/>
    <language>en</language>
    <item>
      <title>KoutenDB v0.10.0: 72 Hours, Three Persistent Nodes, and Zero Client Errors</title>
      <dc:creator>puffball1567</dc:creator>
      <pubDate>Mon, 03 Aug 2026 12:23:51 +0000</pubDate>
      <link>https://dev.to/puffball1567/koutendb-v0100-72-hours-three-persistent-nodes-and-zero-client-errors-1n2m</link>
      <guid>https://dev.to/puffball1567/koutendb-v0100-72-hours-three-persistent-nodes-and-zero-client-errors-1n2m</guid>
      <description>&lt;p&gt;I released &lt;strong&gt;KoutenDB v0.10.0&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Release:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb/releases/tag/v0.10.0" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb/releases/tag/v0.10.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;KoutenDB is a ring-oriented document and vector database written in Nim. Its core idea is to make an application's locality boundary part of the read path:&lt;br&gt;
place related data together, select that boundary before retrieval, and avoid making unrelated records candidates in the first place.&lt;/p&gt;

&lt;p&gt;That idea needs more than a clean benchmark. A database also has to keep running while it writes persistent state, serves reads, tracks topology state, and eventually shuts down for verification.&lt;/p&gt;

&lt;p&gt;For v0.10.0, I ran a local persistent three-node cluster continuously for 72 hours. The result was simple and useful: the run completed with zero client errors, and all three data directories passed offline verification after the servers stopped.&lt;/p&gt;
&lt;h2&gt;
  
  
  What the endurance run did
&lt;/h2&gt;

&lt;p&gt;The runner started three local TCP nodes with persistence enabled and exercised&lt;br&gt;
a mixed workload every 250 ms for 259,200 seconds.&lt;/p&gt;

&lt;p&gt;The workload included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TCP writes;&lt;/li&gt;
&lt;li&gt;point reads using IDs returned by earlier writes;&lt;/li&gt;
&lt;li&gt;JSON projection queries;&lt;/li&gt;
&lt;li&gt;bounded ring reads with sort and limit;&lt;/li&gt;
&lt;li&gt;ring-scoped exact vector retrieval;&lt;/li&gt;
&lt;li&gt;metrics collection;&lt;/li&gt;
&lt;li&gt;a final snapshot and offline verification after shutdown.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The runner builds its own copy of the server, CLI, and workload binaries under the run directory before it starts. This matters because rebuilding the source tree during a long run cannot silently change the executable being tested.&lt;/p&gt;

&lt;p&gt;The exact run used commit &lt;code&gt;87c755c9130ec0bbf70a3903c75fd2bdae8b084b&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Final result
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Completed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;969,281&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;returned-ID GET&lt;/td&gt;
&lt;td&gt;969,281&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;projection query&lt;/td&gt;
&lt;td&gt;969,281&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bounded ring read&lt;/td&gt;
&lt;td&gt;969,281&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ring-scoped retrieve&lt;/td&gt;
&lt;td&gt;96,928&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;metrics read&lt;/td&gt;
&lt;td&gt;48,464&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;client errors&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is &lt;strong&gt;4,022,516 completed logical client operations&lt;/strong&gt; across the 72-hour period.&lt;/p&gt;

&lt;p&gt;After the workload finished, the runner took its final snapshot, stopped the three nodes, and ran offline &lt;code&gt;kouten verify&lt;/code&gt; against every persistent data directory. All three verifications succeeded.&lt;/p&gt;

&lt;p&gt;The final operational counters also showed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;zero pending handoffs;&lt;/li&gt;
&lt;li&gt;zero handoff queue depth;&lt;/li&gt;
&lt;li&gt;zero handoff failures, stale acknowledgements, or queue-full events;&lt;/li&gt;
&lt;li&gt;zero remaining migrations;&lt;/li&gt;
&lt;li&gt;zero universe-sync errors;&lt;/li&gt;
&lt;li&gt;zero global retrieval requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last point is important for KoutenDB's design. The workload used ring-scoped retrieval, and the metrics confirmed that it did not silently fall back to a cluster-wide retrieval path.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why this is more useful than a startup smoke test
&lt;/h2&gt;

&lt;p&gt;A startup test can show that a server accepts a request. It does not show what happens after hundreds of thousands of persistent writes, repeated read paths, periodic metrics calls, topology bookkeeping, and a full stop-and-reopen boundary.&lt;/p&gt;

&lt;p&gt;This run specifically exercised the persistent cluster path over time:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;records were written to disk-backed nodes;&lt;/li&gt;
&lt;li&gt;later requests read data that had been accumulated by the same run;&lt;/li&gt;
&lt;li&gt;cluster handoff and migration counters were observed throughout the run;&lt;/li&gt;
&lt;li&gt;the servers were stopped cleanly;&lt;/li&gt;
&lt;li&gt;the on-disk state was opened and verified offline.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It does establish a concrete baseline: KoutenDB can sustain a mixed, persistent local cluster workload for three days without a client-visible error or an offline integrity failure.&lt;/p&gt;
&lt;h2&gt;
  
  
  What changed in v0.10.0
&lt;/h2&gt;

&lt;p&gt;The endurance runner is one part of a larger operational hardening release.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Operational configuration can now be loaded and verified before a server is
used.&lt;/li&gt;
&lt;li&gt;Write guardrails, audit events, capacity thresholds, and backup verification
provide explicit operational checks.&lt;/li&gt;
&lt;li&gt;Explicit scale-in migration and rolling topology activation add controlled
drain, handoff, and progress behavior.&lt;/li&gt;
&lt;li&gt;Cluster retrieval now remains in the requested ring rather than falling back
to a cluster-wide scan.&lt;/li&gt;
&lt;li&gt;Physical placement is decoupled from the logical orbit schedule, so a
logical orbit boundary does not stall local request processing.&lt;/li&gt;
&lt;li&gt;Handoff I/O is kept off the request loop, and stale handoff replay cannot
resurrect an older mutation.&lt;/li&gt;
&lt;li&gt;The optional FAISS backend was removed. Vector retrieval now follows the
core KoutenDB model directly: select a ring first, then perform exact cosine
ranking over that bounded candidate set.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are not unrelated features. They move the project from a collection of locality experiments toward an operable persistent service: know what the server is configured to do, constrain unsafe operation, observe background state, and verify the data after a long workload.&lt;/p&gt;
&lt;h2&gt;
  
  
  Reproducing the run
&lt;/h2&gt;

&lt;p&gt;The runner is included in the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;KOUTEN_SOAK_SECONDS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;259200 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;KOUTEN_SOAK_WORKDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/koutendb-soak-72h &lt;span class="se"&gt;\&lt;/span&gt;
examples/soak_72h.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It writes JSON Lines progress, node logs, final metrics, a final snapshot, offline verification output, the workload configuration, and a &lt;code&gt;completed.ok&lt;/code&gt; marker only after all final verification steps succeed.&lt;/p&gt;

&lt;p&gt;The full configuration and scope are documented here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb/blob/main/docs/soak-testing.md" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb/blob/main/docs/soak-testing.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The run is intentionally not a CI job. A three-day endurance test is useful because it is long enough to observe persistent operational behavior; it would make normal pull-request feedback unusably slow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The next reliability question
&lt;/h2&gt;

&lt;p&gt;This result validates the current local, disk-backed, buffered-durability cluster mode. The next endurance variants are clear: strong-durability writes, TLS and authenticated transport, Docker/container deployment, and eventually multiple machines.&lt;/p&gt;

&lt;p&gt;Those tests extend this baseline rather than replace it. The v0.10.0 result is now a documented, reproducible reference point for future changes to storage, handoff, topology, and retrieval behavior.&lt;/p&gt;

&lt;p&gt;Source:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>opensource</category>
      <category>nim</category>
      <category>devlog</category>
    </item>
    <item>
      <title>Clay Board Style System update: Link Navigation</title>
      <dc:creator>puffball1567</dc:creator>
      <pubDate>Mon, 03 Aug 2026 11:52:50 +0000</pubDate>
      <link>https://dev.to/puffball1567/clay-board-style-system-update-link-navigation-49gj</link>
      <guid>https://dev.to/puffball1567/clay-board-style-system-update-link-navigation-49gj</guid>
      <description>&lt;p&gt;Clay Board Style System now provides typed native Link Navigation.&lt;/p&gt;

&lt;p&gt;For readability, I will refer to Clay Board Style System as &lt;strong&gt;CBSS&lt;/strong&gt; below.&lt;br&gt;
CBSS is only an abbreviation used in this article; the project's official name&lt;br&gt;
is Clay Board Style System.&lt;/p&gt;

&lt;p&gt;The feature lets a native application move between screens with a flow similar&lt;br&gt;
to a Single-Page Application: the window remains open, the navigation menu&lt;br&gt;
remains in place, and only the active screen changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fybk4il5zie6v1cai8n84.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fybk4il5zie6v1cai8n84.gif" alt="Clay Board Style System navigation demo" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this tutorial, we will build a small navigation menu with three destinations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Home&lt;/li&gt;
&lt;li&gt;Projects&lt;/li&gt;
&lt;li&gt;Settings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clicking a menu item switches the visible screen inside the same native SDL3&lt;br&gt;
window. No DOM, browser history, WebView, or URL-string router is required.&lt;/p&gt;
&lt;h2&gt;
  
  
  Run the finished demo
&lt;/h2&gt;

&lt;p&gt;The complete interactive demo is already included in the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/puffball1567/clay-board-style-system.git
&lt;span class="nb"&gt;cd &lt;/span&gt;clay-board-style-system
nimble setupBundled
nimble navigationDemo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full source is available in&lt;br&gt;
&lt;a href="https://github.com/puffball1567/clay-board-style-system/blob/main/examples/navigation_demo.nim" rel="noopener noreferrer"&gt;&lt;code&gt;examples/navigation_demo.nim&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Define the screens
&lt;/h2&gt;

&lt;p&gt;Start by describing the destinations as a normal Nim enum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;clay_board_style_system&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Screen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt;
  &lt;span class="n"&gt;homeScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;projectsScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;settingsScreen&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;navigator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initStackNavigator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;homeScreen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;navigator&lt;/code&gt; now owns the screen history. The initial destination is&lt;br&gt;
&lt;code&gt;homeScreen&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Because destinations are Nim values, invalid destinations are caught by the&lt;br&gt;
compiler instead of becoming malformed route strings at runtime.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Define a small set of styles
&lt;/h2&gt;

&lt;p&gt;The navigation behavior does not impose a visual design. These styles create a&lt;br&gt;
simple sidebar and content area:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="k"&gt;proc &lt;/span&gt;&lt;span class="nf"&gt;appStyle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="n"&gt;UiStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;uiStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;520&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"flex-direction"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"row"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"background-color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;colorValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.04&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;proc &lt;/span&gt;&lt;span class="nf"&gt;menuStyle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="n"&gt;UiStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;uiStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;220&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;520&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"padding"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"flex-direction"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"column"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"background-color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;colorValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.09&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.13&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;proc &lt;/span&gt;&lt;span class="nf"&gt;contentStyle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="n"&gt;UiStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;uiStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;680&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;520&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"relative"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"overflow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;proc &lt;/span&gt;&lt;span class="nf"&gt;screenStyle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="n"&gt;UiStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;uiStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"absolute"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"left"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;680&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;520&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"padding"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"flex-direction"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"column"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"background-color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;colorValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.04&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;proc &lt;/span&gt;&lt;span class="nf"&gt;linkStyle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="n"&gt;UiStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;uiStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"padding"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"align-items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"background-color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;colorValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.21&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"border-radius"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cursor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pointer"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;proc &lt;/span&gt;&lt;span class="nf"&gt;linkTextStyle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="n"&gt;UiStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;uiStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"font-size"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"line-height"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;colorValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.91&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.94&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.98&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are ordinary CBSS styles. A component library can replace all of them&lt;br&gt;
without changing the navigation code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3: Build the menu and screens
&lt;/h2&gt;

&lt;p&gt;Keep the three screen roots so they can be registered with the navigator. We&lt;br&gt;
also keep the Back and Forward buttons for the next step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;AppView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt;
  &lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NodeHandle&lt;/span&gt;
  &lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NodeHandle&lt;/span&gt;
  &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NodeHandle&lt;/span&gt;
  &lt;span class="n"&gt;backButton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ButtonHandle&lt;/span&gt;
  &lt;span class="n"&gt;forwardButton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ButtonHandle&lt;/span&gt;
  &lt;span class="n"&gt;refreshProjects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ButtonHandle&lt;/span&gt;
  &lt;span class="n"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CheckboxHandle&lt;/span&gt;

&lt;span class="k"&gt;proc &lt;/span&gt;&lt;span class="nf"&gt;buildView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UiRoot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Navigator&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;AppView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;appStyle&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
    &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;menuStyle&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
      &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"My application"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;homeScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Home"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkStyle&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;textStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkTextStyle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;projectsScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Projects"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkStyle&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;textStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkTextStyle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;settingsScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Settings"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkStyle&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;textStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkTextStyle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Back"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forwardButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Forward"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contentStyle&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
      &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;screenStyle&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
        &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Home"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Welcome to the native application."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;screenStyle&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
        &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Projects"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Project data will be displayed here."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;refreshProjects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Refresh projects"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;screenStyle&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
        &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Settings"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notifications&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
          &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;checkbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enable notifications"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hierarchy is visible directly in the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;application
├── navigation menu
│   ├── Home Link
│   ├── Projects Link
│   ├── Settings Link
│   ├── Back button
│   └── Forward button
└── content area
    ├── Home screen
    ├── Projects screen
    └── Settings screen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ui.link()&lt;/code&gt; is a style-neutral native Link. It handles pointer activation,&lt;br&gt;
Enter-key activation, keyboard focus, disabled state, and accessibility&lt;br&gt;
semantics.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 4: Register the screens
&lt;/h2&gt;

&lt;p&gt;Build the view once, then associate each typed destination with its screen root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ui&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initUiRoot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;navigator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initStackNavigator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;homeScreen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buildView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initNavigationScreenHost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;registerScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;homeScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;registerScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;projectsScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;registerScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settingsScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;interaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initInteractionState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;newException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"initial screen could not be activated"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, only Home is active.&lt;/p&gt;

&lt;p&gt;When a Link receives a click or Enter-key event, it updates the navigator. After&lt;br&gt;
the current platform-event batch, synchronize the screen host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;screenChanged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a real application this line belongs in the central event loop, after CBSS&lt;br&gt;
has dispatched the current batch of SDL3 events. The complete demo shows that&lt;br&gt;
integration without hiding it behind tutorial pseudocode.&lt;/p&gt;

&lt;p&gt;Only the active screen participates in layout, painting, hit testing, keyboard&lt;br&gt;
focus, and the visible accessibility tree. The other screens remain retained&lt;br&gt;
but inert.&lt;/p&gt;

&lt;p&gt;That is the SPA-like part: switching screens does not reconstruct the complete&lt;br&gt;
application tree or open another native window.&lt;/p&gt;
&lt;h2&gt;
  
  
  Add Back and Forward
&lt;/h2&gt;

&lt;p&gt;The same navigator provides history operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;proc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DispatchResult&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;back&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s"&gt;"Already at the first screen"&lt;/span&gt;
  &lt;span class="kp"&gt;true&lt;/span&gt;

&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forwardButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;proc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DispatchResult&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s"&gt;"Already at the latest screen"&lt;/span&gt;
  &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;push&lt;/code&gt;, &lt;code&gt;replace&lt;/code&gt;, &lt;code&gt;back&lt;/code&gt;, and &lt;code&gt;forward&lt;/code&gt; operate on typed history entries. Two&lt;br&gt;
visits to Projects remain two separate entries, which allows CBSS to restore&lt;br&gt;
focus for the correct visit when navigating through history.&lt;/p&gt;
&lt;h2&gt;
  
  
  Request data with Joubako
&lt;/h2&gt;

&lt;p&gt;Navigation belongs to CBSS, while HTTP communication belongs to the&lt;br&gt;
application's data layer.&lt;/p&gt;

&lt;p&gt;I am also developing&lt;br&gt;
&lt;a href="https://github.com/puffball1567/joubako" rel="noopener noreferrer"&gt;&lt;code&gt;Joubako&lt;/code&gt;&lt;/a&gt;, a separate async transport&lt;br&gt;
client for Nim. It supports HTTP(S), typed JSON, standard Nim &lt;code&gt;await&lt;/code&gt;,&lt;br&gt;
result-aware callback composition, WebSockets, local IPC, and optional NIF/BIF&lt;br&gt;
data exchange.&lt;/p&gt;

&lt;p&gt;It can be started from a normal CBSS event handler without coupling networking&lt;br&gt;
to the navigation system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;asyncdispatch&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;joubako&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Project&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newHttpTransport&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"https://api.example.com/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;proc &lt;/span&gt;&lt;span class="nf"&gt;loadProjects&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{.&lt;/span&gt;&lt;span class="n"&gt;async&lt;/span&gt;&lt;span class="p"&gt;.}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"projects"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;seq&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Project&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isErr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s"&gt;"Request failed: "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;

  &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s"&gt;"Loaded projects: "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;
  &lt;span class="c"&gt;# Update application state and mark the affected view dirty here.&lt;/span&gt;

&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;refreshProjects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;proc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DispatchResult&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;asyncCheck&lt;/span&gt; &lt;span class="n"&gt;loadProjects&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Joubako is not bundled with CBSS and is not required for Link Navigation. An&lt;br&gt;
application can use Joubako, another HTTP client, IPC, an FFI service, or a&lt;br&gt;
fully local data source behind the same event-handler boundary.&lt;/p&gt;
&lt;h2&gt;
  
  
  Optional features
&lt;/h2&gt;

&lt;p&gt;The basic menu above is enough for normal in-process screen navigation. CBSS&lt;br&gt;
also provides optional APIs for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;focus restoration for each history entry;&lt;/li&gt;
&lt;li&gt;animated screen transitions;&lt;/li&gt;
&lt;li&gt;validated application deep links;&lt;/li&gt;
&lt;li&gt;replacing one retained screen without rebuilding the application; and&lt;/li&gt;
&lt;li&gt;injecting a custom navigation driver.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These features are documented in the&lt;br&gt;
&lt;a href="https://github.com/puffball1567/clay-board-style-system/blob/main/docs/navigation.md" rel="noopener noreferrer"&gt;&lt;code&gt;Native Navigation guide&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why use typed destinations?
&lt;/h2&gt;

&lt;p&gt;A browser URL is useful when the URL is the application's public address. A&lt;br&gt;
native in-process screen does not always need that string boundary.&lt;/p&gt;

&lt;p&gt;With CBSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="n"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;projectsScreen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is checked against &lt;code&gt;Screen&lt;/code&gt; by Nim. A larger application can replace the enum&lt;br&gt;
with a variant object that carries typed parameters, such as a project ID.&lt;/p&gt;

&lt;p&gt;External deep links can still be decoded into the same destination type at the&lt;br&gt;
edge of the application. Internal navigation remains typed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current status
&lt;/h2&gt;

&lt;p&gt;Clay Board Style System v0.3 is a developer preview. Linux x86_64 with SDL3 is&lt;br&gt;
currently the Tier 1 runtime. Windows and macOS portable builds run in CI, while&lt;br&gt;
complete runtime validation on those platforms remains contributor-driven.&lt;/p&gt;

&lt;p&gt;Link Navigation is covered by unit tests, retained-screen tests, transition and&lt;br&gt;
focus tests, performance checks, and a real SDL3/Wayland E2E scenario.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/puffball1567/clay-board-style-system" rel="noopener noreferrer"&gt;Clay Board Style System&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/puffball1567/clay-board-style-system/blob/main/docs/navigation.md" rel="noopener noreferrer"&gt;Native Navigation guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/puffball1567/clay-board-style-system/blob/main/examples/navigation_demo.nim" rel="noopener noreferrer"&gt;Complete navigation demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/puffball1567/clay-board-style-system/releases/tag/v0.3.0" rel="noopener noreferrer"&gt;Clay Board Style System v0.3.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/puffball1567/joubako" rel="noopener noreferrer"&gt;Joubako&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback on the Link API and the navigation-menu authoring experience is very&lt;br&gt;
welcome.&lt;/p&gt;

</description>
      <category>nim</category>
      <category>gui</category>
      <category>native</category>
      <category>opensource</category>
    </item>
    <item>
      <title>RAG Retrieval Optimization: Reduce Vector Search Before Ranking</title>
      <dc:creator>puffball1567</dc:creator>
      <pubDate>Mon, 03 Aug 2026 04:21:03 +0000</pubDate>
      <link>https://dev.to/puffball1567/rag-retrieval-optimization-reduce-vector-search-before-ranking-5h16</link>
      <guid>https://dev.to/puffball1567/rag-retrieval-optimization-reduce-vector-search-before-ranking-5h16</guid>
      <description>&lt;p&gt;Most RAG performance advice begins at the ranking stage: choose a faster embedding model, tune an ANN index, reduce the result count, add a reranker, or cache common queries.&lt;/p&gt;

&lt;p&gt;Those are useful techniques. But RAG retrieval optimization should start one step earlier:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why is this query considering these vectors at all?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A request often already contains a reliable boundary: tenant, repository, product, language, document type, version, date range, permission scope, or the object currently open in the application. Applying that knowledge before vector ranking can reduce RAG latency, vector-search memory use, and unrelated context.&lt;/p&gt;

&lt;p&gt;This is the difference between searching a whole corpus for similar documents and searching the authorized, relevant part of that corpus. It is also the specific problem that a locality-aware RAG database such as&lt;br&gt;
&lt;a href="https://github.com/puffball1567/koutendb" rel="noopener noreferrer"&gt;KoutenDB&lt;/a&gt; explores.&lt;/p&gt;
&lt;h2&gt;
  
  
  Vector search metadata filtering is not one operation
&lt;/h2&gt;

&lt;p&gt;Vector search metadata filtering commonly restricts a query by fields such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tenant_id = "acme"
AND product = "billing"
AND language = "en"
AND published = true
AND version = "2026.2"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those constraints are necessary for both relevance and security. Their placement in the read path, however, changes the cost:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Filter after broad retrieval&lt;/td&gt;
&lt;td&gt;Rank widely, then discard ineligible candidates.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Filter-aware vector index&lt;/td&gt;
&lt;td&gt;Use indexed metadata while selecting vector candidates.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Namespace or partition selection&lt;/td&gt;
&lt;td&gt;Select an eligible subset, then search it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Application-local routing&lt;/td&gt;
&lt;td&gt;Route directly to a known tenant, source, or related-data neighborhood.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The first approach can still enforce correct access rules, but it may score vectors that should never have been candidates. The latter two are valuable when the application already knows a stable boundary.&lt;/p&gt;

&lt;p&gt;For a multi-tenant support assistant, the tenant boundary is not merely a relevance hint. It is an authorization rule and a natural first search scope.&lt;br&gt;
For a code assistant, the active repository and branch often serve the same purpose. For a product assistant, version and language can rule out most of the corpus before similarity becomes useful.&lt;/p&gt;
&lt;h2&gt;
  
  
  RAG optimization starts with the working set
&lt;/h2&gt;

&lt;p&gt;The working set is everything a request touches: candidate vectors, metadata,payload bytes, reranker inputs, and finally model context. Reducing it changes several costs at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fewer vectors to score;&lt;/li&gt;
&lt;li&gt;less vector memory to read;&lt;/li&gt;
&lt;li&gt;fewer payloads to filter and project;&lt;/li&gt;
&lt;li&gt;fewer candidates for a reranker;&lt;/li&gt;
&lt;li&gt;less irrelevant context competing for the prompt budget.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not an argument for creating a partition for every tag. A pre-ranking boundary should be stable, known at request time, meaningful to the application,and strong enough to exclude large amounts of unrelated data. Tenant, source,product, and document-version boundaries often qualify; free-form tags usually do not.&lt;/p&gt;

&lt;p&gt;There is also an essential quality check: a smaller scope is only an optimization if it retains the documents the user needs. A wrong partition can be fast because it is wrong.&lt;/p&gt;
&lt;h2&gt;
  
  
  KoutenDB: locality first, exact vector ranking second
&lt;/h2&gt;

&lt;p&gt;KoutenDB is an open-source, embedded-capable document and vector database written in Nim. It is not a general replacement for PostgreSQL, a mature ANN vector database, or a global secondary-index engine.&lt;/p&gt;

&lt;p&gt;Its vector path makes a focused trade-off:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the application chooses a ring, a semantic locality boundary;&lt;/li&gt;
&lt;li&gt;KoutenDB retrieves candidates from that ring;&lt;/li&gt;
&lt;li&gt;it performs dependency-free exact cosine ranking over that bounded set.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, a RAG application that already knows the tenant and product can place and query documentation in a corresponding ring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;koutendb&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;koutendb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;@[&lt;/span&gt;&lt;span class="mf"&gt;1.0'f32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0'f32&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;ring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"tenant/acme/product/billing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;budget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ring is chosen by application logic, policy, or an import rule; KoutenDB does not claim to infer the right security or business boundary from embedding similarity. JSONL ingestion can derive rings from a field, for example with a tenant field and a tenant prefix.&lt;/p&gt;

&lt;p&gt;Filters and projections still narrow results, but only after the local ring has been selected. This boundary is important: KoutenDB is a good fit when an application can name a meaningful pre-ranking scope. It is not the right primary tool when every query must perform global, cross-corpus discovery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure vectors scanned, not only results returned
&lt;/h2&gt;

&lt;p&gt;Returning fewer hits does not prove that a system did less search work. A useful RAG database should expose whether unrelated candidates were skipped before ranking.&lt;/p&gt;

&lt;p&gt;KoutenDB reports total vectors, scanned candidates, skipped vectors, rings touched, candidate reduction, payload bytes, and estimated tokens. Its included working-set benchmark uses 10,000 vectors across 100 rings. In one local run, global retrieval scanned 10,000 vectors per query, while routed retrieval scanned 100: a 99% reduction. Measured latency in that run was 1,954.9 microseconds for the global path and 31.4 microseconds for the routed path.&lt;/p&gt;

&lt;p&gt;An included RAG-style test kept recall at 1.000 for the correctly routed ring while reducing scanned candidates from 400 to 40 and estimated tokens from 615.2 to 231.6. It also demonstrates the failure case: selecting the wrong ring keeps the small scan but produces zero recall.&lt;/p&gt;

&lt;p&gt;These are local synthetic measurements, not a universal latency claim or a claim that KoutenDB beats every vector database. They demonstrate a narrower invariant: candidates in unrelated rings are skipped before exact vector scoring, rather than discarded after a broad search.&lt;/p&gt;

&lt;h2&gt;
  
  
  When locality-first retrieval is useful
&lt;/h2&gt;

&lt;p&gt;This approach is particularly relevant for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;multi-tenant RAG and tenant-based data isolation;&lt;/li&gt;
&lt;li&gt;support systems scoped to a customer, product, or deployment;&lt;/li&gt;
&lt;li&gt;code assistants scoped to a repository or service;&lt;/li&gt;
&lt;li&gt;documentation assistants with known language and version;&lt;/li&gt;
&lt;li&gt;local AI or desktop applications with a bounded local corpus;&lt;/li&gt;
&lt;li&gt;systems that need nearby application history as well as similar chunks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is less suitable when global discovery is the core job, or when the application cannot identify a trustworthy boundary before retrieval. In that case, a broad ANN-oriented vector database with filter-aware indexing is often the better primary retrieval layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  A checklist for RAG retrieval optimization
&lt;/h2&gt;

&lt;p&gt;Before tuning a model or index, ask:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Which tenant, permission, source, version, or task boundary is known before retrieval?&lt;/li&gt;
&lt;li&gt;Is that boundary enforced before candidates are ranked?&lt;/li&gt;
&lt;li&gt;How many vectors are scanned, rather than merely returned?&lt;/li&gt;
&lt;li&gt;Does scoped retrieval preserve recall on representative queries?&lt;/li&gt;
&lt;li&gt;Can the system explain why each document was eligible?&lt;/li&gt;
&lt;li&gt;Are payload projection and context budgets applied before the LLM call?&lt;/li&gt;
&lt;li&gt;Can the same routing rules be validated offline?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The answer may lead to namespaces, metadata indexes, database partitions, or a locality-aware database. The common requirement is to make the pre-ranking boundary explicit and measurable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The best way to reduce RAG cost or RAG latency is not always a more complicated ranking algorithm. Often it is avoiding a ranking problem that the application already knows is irrelevant.&lt;/p&gt;

&lt;p&gt;Use metadata filtering for correctness. Use tenant, source, version, and task locality to reduce the eligible search space when those boundaries are trustworthy. Then measure scanned candidates, recall, latency, and context size together.&lt;/p&gt;

&lt;p&gt;That is the design space KoutenDB explores: a database for RAG where application-level locality becomes part of the retrieval path before exact vector ranking begins.&lt;/p&gt;

</description>
      <category>rag</category>
      <category>database</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>KoutenDB v0.9.0: From a Locality Experiment to a Testable Database</title>
      <dc:creator>puffball1567</dc:creator>
      <pubDate>Sun, 02 Aug 2026 11:09:04 +0000</pubDate>
      <link>https://dev.to/puffball1567/koutendb-v090-from-a-locality-experiment-to-a-testable-database-2api</link>
      <guid>https://dev.to/puffball1567/koutendb-v090-from-a-locality-experiment-to-a-testable-database-2api</guid>
      <description>&lt;p&gt;I released &lt;strong&gt;KoutenDB v0.9.0&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Release:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb/releases/tag/v0.9.0" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb/releases/tag/v0.9.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;KoutenDB is a ring-oriented NoSQL document and vector database written in Nim.&lt;br&gt;
Its central idea is deliberately narrow: when an application already knows a useful locality boundary, that knowledge should reduce the data a request has to inspect.&lt;/p&gt;

&lt;p&gt;Previous releases established the data model, public API, native C ABI, and language-driver foundation. v0.9.0 concentrates on a harder question: can that locality model be tested against a realistic, persistent related-data read shape rather than only described as a design idea?&lt;/p&gt;

&lt;p&gt;This is still a technical preview. It is not a claim that KoutenDB replaces PostgreSQL, Redis, or every document store. The goal of this release is to make the narrower claim measurable and reproducible.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Request Shape: One Entity, Several Bounded Collections
&lt;/h2&gt;

&lt;p&gt;Many web application detail pages need more than one record. A user page, for example, may need a profile, a few addresses, recent employment entries, preferences, recent orders, and notifications. Each collection has its own limit and sort order.&lt;/p&gt;

&lt;p&gt;In a relational database, this can be expressed with several indexed queries or with a JSON aggregate query built from limited subqueries. Both are valid approaches. The question KoutenDB explores is different: if these collections are already known to belong to one user, can that relationship be represented as bounded nearby data from the start?&lt;/p&gt;

&lt;p&gt;v0.9.0 models the example as subrings below a user ring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kouten get &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;users&lt;/span&gt;/&amp;lt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--subring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;profile,addresses,career,preferences,orders,notifications &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--subring-limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;profile:1,addresses:3,career:2,preferences:1,orders:10,notifications:5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--subring-rsort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;orders:time,notifications:time
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This says exactly what the endpoint needs: retrieve six nearby collections, with independent bounds. It is not a general query language and it is not intended to be one. The useful property is that the caller supplies the locality boundary before the read begins.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Changed in v0.9.0
&lt;/h2&gt;

&lt;p&gt;The release adds a benchmark for that heterogeneous related-data bundle and strengthens the corresponding read path.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;readStellar&lt;/code&gt; now prepares projection state once and reuses it across
subrings.&lt;/li&gt;
&lt;li&gt;Stellar reads validate per-subring limits and descending time sorts.&lt;/li&gt;
&lt;li&gt;Simple embedded reads with an empty filter, a positive limit, and &lt;code&gt;id&lt;/code&gt; or
&lt;code&gt;time&lt;/code&gt; ordering can use a bounded ring-window read path.&lt;/li&gt;
&lt;li&gt;Disk-backed segment reads reuse cached streams instead of repeatedly opening
the same segment files.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;import-jsonl&lt;/code&gt; supports chunked commits through &lt;code&gt;--batch-size=N&lt;/code&gt; for larger
data imports.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point of these changes is not an isolated micro-optimization. A locality model only helps if its normal persistent read path remains bounded when the dataset grows.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Reproducible Related-Data Comparison
&lt;/h2&gt;

&lt;p&gt;The repository now includes a helper that builds fresh temporary KoutenDB and PostgreSQL data directories, loads the same logical user dataset, and measures the related-data bundle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10000 &lt;span class="nv"&gt;READS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1000 examples/subring_bundle_postgres_bench.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One local run on 2026-07-21 used an AMD Ryzen 5 5600H, Linux 6.8, Nim 2.2.10, and PostgreSQL 14.23.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Users&lt;/th&gt;
&lt;th&gt;Logical records&lt;/th&gt;
&lt;th&gt;System and query shape&lt;/th&gt;
&lt;th&gt;Returned records&lt;/th&gt;
&lt;th&gt;Read latency&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;1,050,000&lt;/td&gt;
&lt;td&gt;KoutenDB &lt;code&gt;users/&amp;lt;id&amp;gt;/*&lt;/code&gt; stellar read with per-subring bounds&lt;/td&gt;
&lt;td&gt;22 across 6 rings&lt;/td&gt;
&lt;td&gt;196.859 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;1,050,000&lt;/td&gt;
&lt;td&gt;PostgreSQL: six indexed &lt;code&gt;SELECT&lt;/code&gt; statements&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;515 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;1,050,000&lt;/td&gt;
&lt;td&gt;PostgreSQL: JSON aggregate over indexed limited subqueries&lt;/td&gt;
&lt;td&gt;1 JSON bundle&lt;/td&gt;
&lt;td&gt;236 us&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These numbers describe one machine and one workload; they are not a universal database ranking. PostgreSQL's aggregate form is close to the measured KoutenDB result, and it expresses the result through a different but perfectly&lt;br&gt;
reasonable abstraction. The value of the comparison is to keep the claim honest: KoutenDB's ring and subring model should be judged on workloads where the application can name a local working set.&lt;/p&gt;
&lt;h2&gt;
  
  
  Testing the Larger Locality Claim
&lt;/h2&gt;

&lt;p&gt;v0.9.0 also records the completed disk-backed effect-validation run on generated data. The validation imports deterministic JSONL corpora and compares broad retrieval with ring-routed retrieval. It reports import time, records scanned, estimated token volume, and retrieval latency.&lt;/p&gt;

&lt;p&gt;The standard scale-1000 matrix completed locally with a largest case of 13,500,000 documents.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workload&lt;/th&gt;
&lt;th&gt;Broad scan&lt;/th&gt;
&lt;th&gt;Ring-routed scan&lt;/th&gt;
&lt;th&gt;Estimated tokens: broad -&amp;gt; routed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;small-balanced&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;168,000&lt;/td&gt;
&lt;td&gt;24,000&lt;/td&gt;
&lt;td&gt;692 -&amp;gt; 260&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;near-distractors&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1,860,000&lt;/td&gt;
&lt;td&gt;120,000&lt;/td&gt;
&lt;td&gt;1,730 -&amp;gt; 433&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;medium-noisy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;13,500,000&lt;/td&gt;
&lt;td&gt;500,000&lt;/td&gt;
&lt;td&gt;2,595 -&amp;gt; 692&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The token column is an estimate for the generated retrieval payloads, not a benchmark of any model. More generally, this validation is not limited to AI workloads. Scanned records, transferred data, candidate memory, and downstream application work all increase when a request must inspect unrelated data.&lt;/p&gt;

&lt;p&gt;The important result is that the test makes the expected trade-off visible:&lt;br&gt;
locality can reduce the candidate set when the application supplies a valid ring boundary. It cannot invent a useful boundary when the application has none.&lt;/p&gt;
&lt;h2&gt;
  
  
  Offline Validation Before Production Traffic
&lt;/h2&gt;

&lt;p&gt;The release also adds an offline JSONL path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;KOUTEN_REAL_JSONL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/path/to/export.jsonl &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;QUERY_RING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;docs/japan &lt;span class="se"&gt;\&lt;/span&gt;
examples/offline_effect_validation.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is intended for copied or exported data rather than a production service.&lt;br&gt;
It gives a team a way to test whether a proposed ring layout narrows its own workload before asking the database to serve live traffic.&lt;/p&gt;

&lt;p&gt;That boundary matters. A database experiment should be reproducible without requiring production credentials, traffic capture, or an unbounded benchmark environment.&lt;/p&gt;
&lt;h2&gt;
  
  
  Verification Included in the Release
&lt;/h2&gt;

&lt;p&gt;The v0.9.0 release state was checked with Nim module checks, the public API test program, the smoke suite, package validation, and whitespace validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nim check src/kouten/store.nim
nim check src/koutendb.nim
nim check src/koutencli.nim
nim check tests/tapi.nim
nim c &lt;span class="nt"&gt;--nimcache&lt;/span&gt;:/tmp/nimcache_kouten_tapi &lt;span class="nt"&gt;-r&lt;/span&gt; tests/tapi.nim
scripts/test_all_smoke.sh
nimble check
git diff &lt;span class="nt"&gt;--check&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The largest generated run remains an explicit manual validation rather than a default CI job. It is valuable precisely because it exercises a scale that a quick smoke test should not pretend to cover.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Comes Next
&lt;/h2&gt;

&lt;p&gt;v0.9.0 makes the locality hypothesis easier to test with persistent data and a concrete web-style read shape. The next work is about making that evaluation more operable: verification commands, controlled drain and snapshot workflows, backup checks, audit records, and safer topology transitions.&lt;/p&gt;

&lt;p&gt;Those are v0.10 development goals, not claims included in v0.9.0.&lt;/p&gt;

&lt;p&gt;KoutenDB remains an early project, but the direction is now more concrete:&lt;br&gt;
data locality should be a testable part of a database read path, not only a diagram or a benchmark headline.&lt;/p&gt;

&lt;p&gt;Source and release notes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>opensource</category>
      <category>nim</category>
      <category>rag</category>
    </item>
    <item>
      <title>Introducing Clay Board Style System: CSS-Inspired Native UI for Nim</title>
      <dc:creator>puffball1567</dc:creator>
      <pubDate>Sun, 02 Aug 2026 10:59:52 +0000</pubDate>
      <link>https://dev.to/puffball1567/introducing-clay-board-style-system-css-inspired-native-ui-for-nim-346a</link>
      <guid>https://dev.to/puffball1567/introducing-clay-board-style-system-css-inspired-native-ui-for-nim-346a</guid>
      <description>&lt;p&gt;I am releasing the first developer preview of &lt;strong&gt;Clay Board Style System&lt;/strong&gt;, a&lt;br&gt;
CSS-inspired primitive engine for native GUI toolkits written in Nim.&lt;/p&gt;

&lt;p&gt;For brevity, this article refers to Clay Board Style System as &lt;strong&gt;CBSS&lt;/strong&gt; after&lt;br&gt;
this point. CBSS is only an abbreviation used in writing; the project's&lt;br&gt;
official name is Clay Board Style System.&lt;/p&gt;

&lt;p&gt;Clay Board Style System starts from a simple observation: Web frontend work is&lt;br&gt;
productive partly because CSS gives many frameworks a shared vocabulary for&lt;br&gt;
layout and visual design. Native GUI development often has to rebuild that&lt;br&gt;
foundation separately for every toolkit.&lt;/p&gt;

&lt;p&gt;The project is an attempt to provide that primitive layer for native&lt;br&gt;
applications without embedding a browser or recreating the Web platform.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/puffball1567/clay-board-style-system" rel="noopener noreferrer"&gt;https://github.com/puffball1567/clay-board-style-system&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fupqbn7vv4q1qwu79t1p5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fupqbn7vv4q1qwu79t1p5.gif" alt="Clay Board Style System demo: native controls, text input, scrolling, and styled layouts" width="760" height="613"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What Clay Board Style System is
&lt;/h2&gt;

&lt;p&gt;Clay Board Style System provides a tree of primitive &lt;code&gt;Box&lt;/code&gt;, &lt;code&gt;Text&lt;/code&gt;, and &lt;code&gt;Image&lt;/code&gt;&lt;br&gt;
nodes, along with typed styles, layout, paint commands, hit testing, focus,&lt;br&gt;
input dispatch, retained scrolling, and accessibility semantics.&lt;/p&gt;

&lt;p&gt;The authoring model intentionally uses familiar CSS ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;spacing, borders, radii, colors, and typography;&lt;/li&gt;
&lt;li&gt;row and column layout, alignment, sizing, clipping, and scrolling;&lt;/li&gt;
&lt;li&gt;absolute and overlay positioning;&lt;/li&gt;
&lt;li&gt;state styling for hover, active, focus, and disabled states.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The aim is that someone who can read a Web design article or a CSS example can&lt;br&gt;
bring much of its layout and visual reasoning to a native application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uiStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
  &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"padding"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
  &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
  &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"background-color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;colorValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.16&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;
  &lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"border-radius"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
  &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A native UI, styled with familiar ideas"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What it is not
&lt;/h2&gt;

&lt;p&gt;Clay Board Style System is not a browser, a WebView, an HTML renderer, or a&lt;br&gt;
full CSS implementation. It does not aim for DOM compatibility, JavaScript,&lt;br&gt;
browser quirks, or bug-for-bug CSS behavior.&lt;/p&gt;

&lt;p&gt;It is also not a finished component library. Buttons, dialogs, menus, inputs,&lt;br&gt;
and editors should be built as compositions on top of the primitive layer.&lt;/p&gt;

&lt;p&gt;This boundary matters. The goal is to reuse the useful language of Web UI&lt;br&gt;
design while keeping a native rendering, input, and application model.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Nim
&lt;/h2&gt;

&lt;p&gt;The first implementation target is Nim because it can produce small native&lt;br&gt;
applications while remaining expressive enough for UI composition. Clay Board&lt;br&gt;
Style System also exposes a versioned C ABI with opaque handles and fixed-size&lt;br&gt;
value structs. That lets an existing C, C++, Rust, Zig, or Swift core be paired&lt;br&gt;
with a Nim frontend, rather than requiring a rewrite before the UI can be&lt;br&gt;
explored.&lt;/p&gt;

&lt;p&gt;My hope is that this creates a practical entry point to Nim: keep the existing&lt;br&gt;
engine or product core, build the frontend in Nim, and adopt Nim more broadly&lt;br&gt;
only where it proves useful.&lt;/p&gt;
&lt;h2&gt;
  
  
  Current developer preview
&lt;/h2&gt;

&lt;p&gt;Version 0.2 targets Linux x86_64 with SDL3. It includes the primitive&lt;br&gt;
style/layout pipeline, text shaping through cosmic-text, event routing, focus,&lt;br&gt;
text input and IME integration, retained scrolling, navigation state, a&lt;br&gt;
semantic accessibility model, and the C ABI.&lt;/p&gt;

&lt;p&gt;The project is still early. Windows and macOS require contributor validation;&lt;br&gt;
platform accessibility transports, animation timelines, full rich-text layout,&lt;br&gt;
and some windowing behavior are not complete. Public APIs may change before&lt;br&gt;
1.0.&lt;/p&gt;

&lt;p&gt;This is therefore a release for people who want to evaluate the approach,&lt;br&gt;
build experiments, and help shape the primitive layer—not a claim that every&lt;br&gt;
desktop application should use it today.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Clay Board Style System requires Nim 2.2 or newer, Rust/Cargo for the native&lt;br&gt;
text and image bridges, and SDL3 development files on the current Linux target.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/puffball1567/clay-board-style-system.git
&lt;span class="nb"&gt;cd &lt;/span&gt;clay-board-style-system
nimble setupBundled
nimble &lt;span class="nb"&gt;test
&lt;/span&gt;nimble sdl3Demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next work is to make the project's visual promise easier to judge: richer&lt;br&gt;
design demos, practical composite controls, and broader platform validation.&lt;br&gt;
Issues, experiments, and feedback are welcome in the repository.&lt;/p&gt;

</description>
      <category>nim</category>
      <category>gui</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>RAG Database Design: SQL, Full-Text Search, Vector Search, and Context Retrieval</title>
      <dc:creator>puffball1567</dc:creator>
      <pubDate>Thu, 23 Jul 2026 14:38:14 +0000</pubDate>
      <link>https://dev.to/puffball1567/rag-database-design-sql-full-text-search-vector-search-and-context-retrieval-9of</link>
      <guid>https://dev.to/puffball1567/rag-database-design-sql-full-text-search-vector-search-and-context-retrieval-9of</guid>
      <description>&lt;p&gt;Retrieval-augmented generation is often introduced with a compact diagram:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;documents -&amp;gt; embeddings -&amp;gt; vector database -&amp;gt; LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a useful starting point, but it can make one part of the architecture&lt;br&gt;
look like the whole system.&lt;/p&gt;

&lt;p&gt;Good RAG database design has to cover more than vector storage.&lt;/p&gt;

&lt;p&gt;A production RAG application may also need to store original documents,&lt;br&gt;
enforce tenant boundaries, find exact product names, filter by date, remember a conversation, invalidate stale content, combine several data sources, and keep the final prompt within a token budget.&lt;/p&gt;

&lt;p&gt;No database becomes a "RAG database" merely by storing embeddings. Different database models solve different parts of retrieval.&lt;/p&gt;

&lt;p&gt;This article looks at the roles of relational databases, document databases, caches, full-text search engines, and vector databases in RAG. It then examines a retrieval problem that is harder to express with similarity alone: finding a useful neighborhood of context when the application knows the center, but not the exact boundary of the answer.&lt;/p&gt;

&lt;p&gt;Among practical AI use cases, this pattern appears in customer support, business-efficiency AI tools for sales, internal knowledge assistants, AI programming automation, and AI agent development. The same retrieval questions also apply to AI assistant development with internal data, where access control and source freshness matter as much as the generated answer.&lt;/p&gt;
&lt;h2&gt;
  
  
  How RAG works—and how it differs from fine-tuning
&lt;/h2&gt;

&lt;p&gt;RAG retrieves external information when a request is made, then places selected evidence into the model's context. Fine-tuning changes model weights. The practical RAG vs fine-tuning differences are therefore about when and where knowledge is introduced.&lt;/p&gt;

&lt;p&gt;RAG is often easier to update, cite, filter, or remove because the knowledge remains outside the model. Fine-tuning can change behavior, style, or learned patterns, but it is not a convenient replacement for a frequently changing document store.&lt;/p&gt;

&lt;p&gt;The main RAG pros and cons follow from that separation. RAG can use current and private sources without retraining the model, but it adds ingestion, retrieval, permissions, evaluation, latency, and operations work. Understanding how AI generation works is not enough: a fluent model can still answer from weak, stale, or unauthorized evidence.&lt;/p&gt;
&lt;h2&gt;
  
  
  Database types and how to build RAG
&lt;/h2&gt;

&lt;p&gt;A more complete RAG pipeline looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source data
  -&amp;gt; ingestion and normalization
  -&amp;gt; document and metadata storage
  -&amp;gt; candidate selection
  -&amp;gt; lexical or vector ranking
  -&amp;gt; reranking and context assembly
  -&amp;gt; LLM
  -&amp;gt; answer and citations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Databases can participate at several stages.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;Typical data&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Source of truth&lt;/td&gt;
&lt;td&gt;Documents, records, revisions, users, permissions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ingestion state&lt;/td&gt;
&lt;td&gt;Jobs, checksums, parser versions, failures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exact filtering&lt;/td&gt;
&lt;td&gt;Tenant, category, status, language, date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lexical retrieval&lt;/td&gt;
&lt;td&gt;Keywords, names, identifiers, error codes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Semantic retrieval&lt;/td&gt;
&lt;td&gt;Embeddings and similarity scores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Session state&lt;/td&gt;
&lt;td&gt;Recent messages, selected sources, cached results&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context assembly&lt;/td&gt;
&lt;td&gt;Related records, projections, token-bounded payloads&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One database can perform several of these jobs. A small application does not need six databases just because six rows appear in the table. The point is to identify the retrieval job before choosing the storage engine. A useful database comparison begins with those jobs, not with a feature-count table.&lt;/p&gt;

&lt;p&gt;When teams research how to build RAG, they often begin with an embedding model or a RAG vector database. A safer order is to identify the source of truth, access rules, update process, exact filters, candidate retrieval method, and evaluation plan first. The vector index is one component of that design.&lt;/p&gt;

&lt;p&gt;To make the differences concrete, imagine that we are building a travel assistant for Kyoto. It stores information about landmarks, restaurants, cultural facilities, events, transit, opening hours, reservations, and user itineraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  PostgreSQL and MySQL: structured truth and exact relationships
&lt;/h2&gt;

&lt;p&gt;Relational databases are often the least surprising place to keep the authoritative application state around a RAG system.&lt;/p&gt;

&lt;p&gt;For the travel assistant, a relational database could store:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;users and accounts;&lt;/li&gt;
&lt;li&gt;bookings and reservations;&lt;/li&gt;
&lt;li&gt;saved places and itineraries;&lt;/li&gt;
&lt;li&gt;tenant or organization boundaries;&lt;/li&gt;
&lt;li&gt;document versions and ingestion status;&lt;/li&gt;
&lt;li&gt;permissions and visibility rules;&lt;/li&gt;
&lt;li&gt;structured opening hours and accessibility fields.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SQL is especially useful when correctness depends on exact relationships. If a private itinerary belongs to one user, or a document must not cross a tenant boundary, that rule should not depend on an embedding score.&lt;/p&gt;

&lt;p&gt;A relational query can select the allowed document IDs first. The RAG pipeline can then rank only those documents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;document_id&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;travel_documents&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Kyoto'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;language&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'en'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;published&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;valid_from&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;valid_until&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PostgreSQL also has JSON, full-text search, and extension support. The &lt;a href="https://github.com/pgvector/pgvector" rel="noopener noreferrer"&gt;&lt;code&gt;pgvector&lt;/code&gt;&lt;/a&gt; extension can keep vectors beside relational data, which is often enough for an early or moderately sized RAG application.&lt;/p&gt;

&lt;p&gt;The important distinction is that adding a vector column does not remove the need to design permissions, document lifecycle, metadata, candidate selection, and prompt construction.&lt;/p&gt;

&lt;h2&gt;
  
  
  MongoDB and document databases: flexible content records
&lt;/h2&gt;

&lt;p&gt;A document database is a natural fit when an ingested item already looks like a JSON object and different item types have different fields.&lt;/p&gt;

&lt;p&gt;A landmark record might contain history, images, coordinates, and opening hours. A restaurant may have cuisine, price range, reservation rules, and dietary options. An event may have a start time, venue, ticket URL, and weather policy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"restaurant"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example Cafe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"area"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Higashiyama"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cuisine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Japanese"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cafe"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"features"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"indoor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"vegetarianOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/core/document/" rel="noopener noreferrer"&gt;MongoDB documents&lt;/a&gt; can&lt;br&gt;
represent that shape without forcing every item type into the same set of columns. Metadata and source text can live together, and nested fields can be indexed when their access patterns are known.&lt;/p&gt;

&lt;p&gt;Flexibility does not eliminate retrieval design, however. The application still has to decide which collection, fields, filters, and records should become candidates for the model.&lt;/p&gt;

&lt;p&gt;The familiar RDB vs NoSQL differences still matter here. Relational systems center exact relationships and constraints; document databases center flexible record shapes and aggregate-oriented access. For business systems, NoSQL database selection criteria should include consistency, authorization, operational skills, backup, and migration—not only whether incoming data is JSON.&lt;/p&gt;
&lt;h2&gt;
  
  
  Redis: short-lived state and repeated work
&lt;/h2&gt;

&lt;p&gt;Redis is useful around RAG even when it is not the primary document store.&lt;/p&gt;

&lt;p&gt;Common uses include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;conversation session state;&lt;/li&gt;
&lt;li&gt;cached retrieval results;&lt;/li&gt;
&lt;li&gt;rate limits;&lt;/li&gt;
&lt;li&gt;short-lived agent state;&lt;/li&gt;
&lt;li&gt;job queues;&lt;/li&gt;
&lt;li&gt;deduplication keys;&lt;/li&gt;
&lt;li&gt;frequently reused context fragments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If many users ask similar questions about the same attraction, caching a validated retrieval result may be cheaper than running the complete pipeline again.&lt;/p&gt;

&lt;p&gt;Redis also supports persistence and several data structures, but a cache still needs an invalidation policy. Travel information makes this obvious: an answer about an event, temporary closure, or opening time can become wrong even when the cached text is internally consistent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://redis.io/docs/latest/develop/get-started/" rel="noopener noreferrer"&gt;Redis documentation&lt;/a&gt;&lt;br&gt;
describes it as more than a simple key/value cache, but its role in a RAG architecture should still be chosen explicitly.&lt;/p&gt;
&lt;h2&gt;
  
  
  OpenSearch: words, fields, and filters still matter
&lt;/h2&gt;

&lt;p&gt;Embedding search is not a replacement for lexical search.&lt;/p&gt;

&lt;p&gt;Users search for exact place names, train lines, product codes, legal terms, error messages, and quoted phrases. A model may produce similar embeddings for related text, but an exact identifier often deserves a lexical match.&lt;/p&gt;

&lt;p&gt;OpenSearch can combine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;full-text queries;&lt;/li&gt;
&lt;li&gt;BM25-style lexical relevance;&lt;/li&gt;
&lt;li&gt;field filters;&lt;/li&gt;
&lt;li&gt;aggregations;&lt;/li&gt;
&lt;li&gt;geographic queries;&lt;/li&gt;
&lt;li&gt;vector search;&lt;/li&gt;
&lt;li&gt;search-oriented dashboards and operational tooling.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the travel assistant, it could answer questions such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Find pages containing "Kiyomizu-dera" in English,
published in the Kyoto corpus, with an opening-hours field updated this month.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That query contains exact text, metadata, and freshness requirements. Those signals should not be reduced to one vector distance.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.opensearch.org/latest/about/" rel="noopener noreferrer"&gt;OpenSearch documentation&lt;/a&gt;&lt;br&gt;
covers both lexical and vector-oriented search, making it a possible single-engine choice when those retrieval modes need to work together.&lt;/p&gt;
&lt;h2&gt;
  
  
  Qdrant and vector databases: semantic similarity
&lt;/h2&gt;

&lt;p&gt;Vector databases are designed around a different question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which stored items are closest to this query in embedding space?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is valuable when the user and document do not share the same words.&lt;/p&gt;

&lt;p&gt;For example, a visitor might ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Where can I spend a quiet indoor afternoon learning about local history?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A useful museum description may not contain that exact sentence. Semantic retrieval can still bring it into the candidate set.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://qdrant.tech/documentation/overview/" rel="noopener noreferrer"&gt;Qdrant&lt;/a&gt; stores vectors with payload metadata and supports filtered similarity search. A typical request first restricts the eligible points, then ranks the remaining points by vector distance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;metadata filter
  -&amp;gt; approximate nearest-neighbor search
  -&amp;gt; top candidates
  -&amp;gt; optional reranker
  -&amp;gt; LLM context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an effective pattern, but it leaves an architectural question: how does the application decide the right filter and search namespace before similarity ranking begins?&lt;/p&gt;

&lt;p&gt;Vector database similarity search algorithms, index type, filtering behavior, memory use, and update patterns all affect the result. A RAG vector DB comparison among Pinecone, Qdrant, pgvector, or OpenSearch should use the application's own corpus and filters. Lists of recommended vector databases cannot replace workload-specific evaluation.&lt;/p&gt;

&lt;h2&gt;
  
  
  RAG hybrid search: BM25, vectors, and reranking
&lt;/h2&gt;

&lt;p&gt;Keyword and semantic retrieval are complementary. A RAG hybrid search pipeline can combine BM25 and vector scores so that exact names and identifiers remain visible while semantically related documents can still be discovered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;metadata and permission filters
  -&amp;gt; BM25 lexical candidates
  + vector similarity candidates
  -&amp;gt; merge and deduplicate
  -&amp;gt; reranker
  -&amp;gt; token-bounded context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For RAG accuracy improvement, rerank integration is often more useful than simply increasing the first-stage result count. A reranker can inspect a small candidate set more carefully, while the first stage remains optimized for recall.&lt;/p&gt;

&lt;p&gt;RAG chunk size optimization techniques matter too. Small chunks can improve matching precision but lose surrounding meaning; large chunks preserve context but consume more tokens and may dilute relevance. The right chunk size depends on document structure, retrieval method, and the unit that must be cited.&lt;/p&gt;

&lt;p&gt;RAG frameworks such as LangChain and LlamaIndex can connect loaders, embeddings, retrievers, and models. A LangChain RAG setup sample can demonstrate the wiring, but a framework cannot decide the correct authorization boundary, freshness rule, or candidate scope for an application.&lt;/p&gt;

&lt;p&gt;An open-source RAG setup for internal search can combine PostgreSQL, OpenSearch or Qdrant, a local model, and an orchestration framework. Self-hosting changes the operations and privacy boundary, but it does not remove the need for the same retrieval and evaluation decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  RAG accuracy improvement and evaluation metrics
&lt;/h2&gt;

&lt;p&gt;Retrieval quality and answer quality should be measured separately. Useful RAG evaluation metrics include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;recall and precision at &lt;code&gt;k&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;mean reciprocal rank or nDCG;&lt;/li&gt;
&lt;li&gt;context relevance and context precision;&lt;/li&gt;
&lt;li&gt;groundedness or faithfulness;&lt;/li&gt;
&lt;li&gt;citation correctness;&lt;/li&gt;
&lt;li&gt;answer completeness;&lt;/li&gt;
&lt;li&gt;retrieved tokens, latency, and cost per request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tools such as Ragas can help automate parts of evaluation, but no RAG evaluation tool or tutorial can define the correct expected answer for every business workflow. A small, reviewed test set from real questions is still valuable.&lt;/p&gt;

&lt;p&gt;RAG hallucination prevention measures should include more than adding extra documents. Stronger measures include current sources, explicit citations, permission checks, conflict detection, an option to abstain, and tests for questions whose answers are not present in the knowledge base.&lt;/p&gt;

&lt;p&gt;RAG knowledge base automated updates also need versioning and invalidation. A pipeline should know which source revision produced a chunk, when an embedding must be rebuilt, and how deleted or expired information leaves caches and indexes.&lt;/p&gt;

&lt;h2&gt;
  
  
  RAG security measures and implementation cost
&lt;/h2&gt;

&lt;p&gt;RAG security measures begin before retrieval. Tenant isolation, source authorization, secret removal, encryption, audit trails, and defenses against prompt injection in retrieved documents all belong in the design. General database security measures still apply even when the database is described as an AI component.&lt;/p&gt;

&lt;p&gt;Organizations may also need to align collection and use of data with privacy rules, sector obligations, AI legal regulations, and their own AI ethics guidelines. Retrieval makes data available to a model; it does not create permission to use that data.&lt;/p&gt;

&lt;p&gt;A complete RAG cost comparison includes ingestion, embedding generation, database storage, cache, network transfer, reranking, LLM input tokens, monitoring, backup, and engineering time. For a small business, the average AI implementation cost cannot be inferred from the model API price alone.&lt;/p&gt;

&lt;p&gt;RAG cost reduction and token savings are closely related to candidate scope.&lt;/p&gt;

&lt;p&gt;Passing fewer irrelevant records through retrieval and reranking can reduce database work and LLM input together. For local deployments, local LLM setup and PC requirements are a separate capacity decision, but smaller retrieved contexts can still reduce downstream memory and compute pressure.&lt;/p&gt;

&lt;p&gt;Many AI implementation failures happen because a demo is evaluated only on a few successful questions. The practical AI implementation benefits appear when the system also handles stale data, missing answers, access boundaries, cost limits, and failure recovery.&lt;/p&gt;

&lt;h2&gt;
  
  
  The difficult part is often candidate scope
&lt;/h2&gt;

&lt;p&gt;Consider this question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I am at Kiyomizu-dera. It is raining, and I have two hours. What should I do&lt;br&gt;
next?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Several retrieval methods can help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lexical search can find pages that mention Kiyomizu-dera;&lt;/li&gt;
&lt;li&gt;geographic search can find coordinates within a radius;&lt;/li&gt;
&lt;li&gt;vector search can find semantically similar travel advice;&lt;/li&gt;
&lt;li&gt;SQL can enforce opening hours, permissions, and reservation constraints;&lt;/li&gt;
&lt;li&gt;a reranker can reorder the resulting candidates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The challenge is not that any one of these methods is bad. The challenge is deciding what should enter the candidate set at all.&lt;/p&gt;

&lt;p&gt;A useful answer may need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nearby landmarks;&lt;/li&gt;
&lt;li&gt;an indoor museum or gallery;&lt;/li&gt;
&lt;li&gt;a restaurant that is currently open;&lt;/li&gt;
&lt;li&gt;a temporary event happening today;&lt;/li&gt;
&lt;li&gt;transit information;&lt;/li&gt;
&lt;li&gt;accessibility information;&lt;/li&gt;
&lt;li&gt;places already present in the user's itinerary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The application knows the center: the visitor, Kiyomizu-dera, the current day, and the current situation. It does not yet know the exact boundary of the useful answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Semantic similarity is not operational relevance
&lt;/h2&gt;

&lt;p&gt;The most semantically similar document is not necessarily the most useful document for the current request.&lt;/p&gt;

&lt;p&gt;A beautifully written article about another Japanese temple may be close in embedding space but unusable within two hours. A short transit notice may be semantically distant from a tourism question but essential to the answer. A restaurant record may contain almost none of the words in the user's request, yet be relevant because it is nearby, open, and compatible with the itinerary.&lt;/p&gt;

&lt;p&gt;RAG systems commonly address this with metadata filters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kyoto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"area"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Higashiyama"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"openNow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"weather"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"restaurant"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"museum"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"landmark"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is reasonable. But as the product grows, the filter becomes an&lt;br&gt;
application-level retrieval plan. Someone must maintain the rules, namespaces, joins, and fan-out reads that reconstruct the context for every request.&lt;/p&gt;
&lt;h2&gt;
  
  
  Geographic distance is not the complete boundary either
&lt;/h2&gt;

&lt;p&gt;If the question is simply "what is within one kilometer?", a geographic index such as PostGIS or OpenSearch geo search is the direct solution.&lt;/p&gt;

&lt;p&gt;Useful travel context is not always a circle, however.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A river, hill, or railway can make two close points inconvenient to reach.&lt;/li&gt;
&lt;li&gt;Rain changes which facilities are useful.&lt;/li&gt;
&lt;li&gt;A family and a solo traveler may need different neighborhoods.&lt;/li&gt;
&lt;li&gt;Opening hours and event dates change the available context.&lt;/li&gt;
&lt;li&gt;Editorial groupings such as "rainy-day Kyoto" are not geographic regions.&lt;/li&gt;
&lt;li&gt;One place can belong to an area guide, a station guide, and a personal
itinerary at the same time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Distance remains an important signal. It is simply not the only relationship that defines the field of view.&lt;/p&gt;
&lt;h2&gt;
  
  
  The application keeps rebuilding context
&lt;/h2&gt;

&lt;p&gt;A conventional stack can solve this problem. It may use SQL joins, geographic indexes, search filters, a graph, application-maintained ID lists, and vector ranking.&lt;/p&gt;

&lt;p&gt;The repeated work is reconstructing the same locality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;start from the current place
  -&amp;gt; identify the area
  -&amp;gt; find allowed categories
  -&amp;gt; join today's events
  -&amp;gt; add relevant transit
  -&amp;gt; add itinerary items
  -&amp;gt; build candidates
  -&amp;gt; rank candidates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The missing operation here is not another scoring algorithm. It is a reusable way to answer this earlier question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What belongs in the neighborhood of this known center for this kind of&lt;br&gt;
request?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Treat the reusable neighborhood as data
&lt;/h2&gt;

&lt;p&gt;One design option is to store that neighborhood instead of reconstructing it from scratch for every request.&lt;/p&gt;

&lt;p&gt;This does not automatically require a new database. An application can model the relationship with SQL junction tables, graph edges, materialized views, search documents, or maintained ID lists. The important change is conceptual:&lt;br&gt;
candidate scope becomes data with its own lifecycle, rather than temporary query logic assembled immediately before ranking.&lt;/p&gt;

&lt;p&gt;For the tourism example, a reusable neighborhood needs a few properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;each place should keep one canonical record;&lt;/li&gt;
&lt;li&gt;the same place should be able to appear in several contexts;&lt;/li&gt;
&lt;li&gt;adding a place to a guide should not copy its payload;&lt;/li&gt;
&lt;li&gt;reads should be bounded by category, depth, filters, limits, and token cost;&lt;/li&gt;
&lt;li&gt;lexical or vector ranking should remain available after the neighborhood is
selected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this relationship is occasional, application code may be enough. If the same pattern appears across users, places, projects, products, or time windows, it can be useful to make locality a first-class retrieval primitive.&lt;/p&gt;
&lt;h2&gt;
  
  
  How KoutenDB represents this retrieval pattern
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb" rel="noopener noreferrer"&gt;KoutenDB&lt;/a&gt; is one database designed&lt;br&gt;
around that pattern. It uses coordinate-like &lt;code&gt;ring&lt;/code&gt; placement for canonical records and &lt;code&gt;stellar&lt;/code&gt; visibility lenses for reusable views across those coordinates.&lt;/p&gt;

&lt;p&gt;An importer or application can keep tourism data in canonical rings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;landmarks/kyoto/kiyomizudera
landmarks/kyoto/yasaka-pagoda
restaurants/kyoto/gion
culture/kyoto/national-museum
events/kyoto/2026-07-23
transit/kyoto/higashiyama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can then attach useful coordinates to an area-centered view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kouten stellar attach &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;landmarks/kyoto/kiyomizudera

kouten stellar attach &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;restaurants/kyoto/gion

kouten stellar attach &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;culture/kyoto/national-museum

kouten stellar attach &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;events/kyoto/2026-07-23
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application can read the surrounding context from the known center:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kouten get &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or narrow the same field of view to one category:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kouten get &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="nt"&gt;--subring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;restaurants
kouten get &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="nt"&gt;--subring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;culture
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same restaurant can also be visible from a rainy-day guide, a&lt;br&gt;
station-centered guide, or a user's itinerary without copying its canonical payload.&lt;/p&gt;

&lt;p&gt;KoutenDB does not infer geographic or editorial relevance from a path name.&lt;/p&gt;

&lt;p&gt;The application, importer, or curation process still decides which coordinates belong in each neighborhood. The database preserves that decision so later reads do not have to reconstruct it from scratch.&lt;/p&gt;
&lt;h2&gt;
  
  
  This is more than a path prefix
&lt;/h2&gt;

&lt;p&gt;A ring name deliberately looks like a readable path. Hierarchy is useful when parent and child data naturally belong together.&lt;/p&gt;

&lt;p&gt;A path prefix alone, however, represents one tree. Real records participate in several views at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;canonical catalog: restaurants/kyoto/gion/example-cafe
area guide:        travel/kyoto/higashiyama
weather guide:     travel/kyoto/rainy-day
personal plan:     travel/users/123/today
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copying the restaurant under every path creates synchronization work. Moving it to one path weakens the other views. A stellar lens instead stores a visibility relationship across existing coordinates.&lt;/p&gt;

&lt;p&gt;The caller supplies a center and a cost boundary. Depth, branch budget, subrings, filters, projections, sorting, and limits control how much context is returned. The caller does not have to enumerate every individual record in the answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Locality can precede vector ranking
&lt;/h2&gt;

&lt;p&gt;Locality-aware retrieval and vector search are not mutually exclusive.&lt;/p&gt;

&lt;p&gt;A combined pipeline can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;known center: user + place + time
  -&amp;gt; retrieve the configured local neighborhood
  -&amp;gt; apply current constraints
  -&amp;gt; vector-rank the smaller candidate set if needed
  -&amp;gt; rerank and enforce a token budget
  -&amp;gt; LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The vector database asks which candidates are semantically close. The locality layer asks which part of the data should be considered first.&lt;/p&gt;

&lt;p&gt;This can reduce the number of payloads loaded, vectors compared, records reranked, bytes transferred, and tokens considered downstream. It does not guarantee that every query becomes faster. The model is useful only when the application can express meaningful locality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Match the database to the retrieval question
&lt;/h2&gt;

&lt;p&gt;The database decision becomes clearer when it starts from the question rather than the current RAG trend.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Retrieval question&lt;/th&gt;
&lt;th&gt;Natural starting point&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Which exact record or relationship is valid?&lt;/td&gt;
&lt;td&gt;Relational query and indexes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Which JSON documents match known fields?&lt;/td&gt;
&lt;td&gt;Document database or SQL/JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Which result can be reused briefly?&lt;/td&gt;
&lt;td&gt;Cache or session store&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Which documents contain these words?&lt;/td&gt;
&lt;td&gt;Full-text search engine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Which documents are semantically similar?&lt;/td&gt;
&lt;td&gt;Vector search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Which places are inside a literal radius?&lt;/td&gt;
&lt;td&gt;Geographic index&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Which context is useful around this known user, place, project, or time?&lt;/td&gt;
&lt;td&gt;Locality-aware neighborhood retrieval&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are not exclusive choices. PostgreSQL may remain the source of truth while OpenSearch handles lexical retrieval. A vector database may rank semantically similar chunks. KoutenDB may be used as a locality-aware document and retrieval store, or as an earlier candidate-selection stage.&lt;/p&gt;

&lt;p&gt;A smaller system may choose one database that covers enough of these roles. A larger system may separate them. Additional infrastructure is justified only when it removes a measured retrieval, correctness, or operations problem.&lt;/p&gt;

&lt;p&gt;Practical database design steps for RAG are therefore:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;identify the authoritative source and update owner;&lt;/li&gt;
&lt;li&gt;define tenant, user, and document access boundaries;&lt;/li&gt;
&lt;li&gt;list exact, lexical, semantic, geographic, and locality-aware queries;&lt;/li&gt;
&lt;li&gt;choose the smallest set of database types that covers those queries;&lt;/li&gt;
&lt;li&gt;measure retrieval quality, tokens, latency, and failure cases;&lt;/li&gt;
&lt;li&gt;document database backup methods and database migration steps for the data that cannot be rebuilt;&lt;/li&gt;
&lt;li&gt;use database performance tuning only after the candidate and access model are correct.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The final question is what the application already knows
&lt;/h2&gt;

&lt;p&gt;RAG architecture often begins by asking which embedding model or vector database to use.&lt;/p&gt;

&lt;p&gt;Another useful question comes first:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What does the application already know before retrieval begins?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It may already know the authenticated user, tenant, order, project, document group, current place, time window, or active task. That information can define a much smaller and more relevant starting region than the complete corpus.&lt;/p&gt;

&lt;p&gt;If the request begins with no meaningful center, global lexical or vector search may be exactly right. If the request begins with a known center but an uncertain context boundary, preserving locality can keep the retrieval problem smaller before ranking and prompt construction begin.&lt;/p&gt;

&lt;p&gt;The important choice is not SQL versus vectors, or one database product versus another. It is deciding whether the application needs exact truth, lexical matching, semantic similarity, geographic proximity, or a reusable neighborhood of context—and then giving each retrieval stage the data model it actually needs.&lt;/p&gt;

&lt;p&gt;That is the foundation of a RAG database design that can grow beyond a demo.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>database</category>
      <category>rag</category>
      <category>llm</category>
    </item>
    <item>
      <title>Why KoutenDB Exists: You Know the Center, Not the Boundary</title>
      <dc:creator>puffball1567</dc:creator>
      <pubDate>Wed, 22 Jul 2026 08:04:06 +0000</pubDate>
      <link>https://dev.to/puffball1567/why-koutendb-exists-you-know-the-center-not-the-boundary-2fga</link>
      <guid>https://dev.to/puffball1567/why-koutendb-exists-you-know-the-center-not-the-boundary-2fga</guid>
      <description>&lt;p&gt;Most database queries begin by describing the answer.&lt;/p&gt;

&lt;p&gt;You provide a primary key, write a SQL predicate, select a collection, enter&lt;br&gt;
search terms, or send an embedding to a vector database. The database then&lt;br&gt;
finds the records that match.&lt;/p&gt;

&lt;p&gt;That model works extremely well, but it is not the shape of every application&lt;br&gt;
request.&lt;/p&gt;

&lt;p&gt;Sometimes the application knows &lt;strong&gt;where the answer should begin&lt;/strong&gt;, while the&lt;br&gt;
complete boundary of useful information is still unclear.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a support request starts with a customer, but may need their profile, recent orders, the product involved, previous tickets, and a refund policy.&lt;/li&gt;
&lt;li&gt;an incident investigation starts with a service and a point in time, but may need a nearby deployment, error logs, metrics, and related service events.&lt;/li&gt;
&lt;li&gt;a RAG request starts with a project or topic, but the useful context may span documents, summaries, source metadata, and attached knowledge.&lt;/li&gt;
&lt;li&gt;a game request starts with a player or place, but may need nearby entities, inventory, quests, and regional state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In each case, the center is known. The exact context boundary is not.&lt;/p&gt;

&lt;p&gt;That is the problem KoutenDB was created to explore.&lt;/p&gt;
&lt;h2&gt;
  
  
  Exact lookup is not the same as context retrieval
&lt;/h2&gt;

&lt;p&gt;Suppose an API receives an order ID.&lt;/p&gt;

&lt;p&gt;Finding the order itself is easy. Almost any database can do that efficiently.&lt;br&gt;
The harder question is what else should travel with it.&lt;/p&gt;

&lt;p&gt;Should the response include the customer? The shop? Recent payment events? The specific product documentation? An unresolved support ticket? The answer may depend on the request, product, current state, and amount of context the caller can afford to process.&lt;/p&gt;

&lt;p&gt;A conventional application can assemble that context with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQL joins;&lt;/li&gt;
&lt;li&gt;several document lookups;&lt;/li&gt;
&lt;li&gt;application-maintained ID lists;&lt;/li&gt;
&lt;li&gt;a graph traversal;&lt;/li&gt;
&lt;li&gt;metadata filters;&lt;/li&gt;
&lt;li&gt;full-text or vector search;&lt;/li&gt;
&lt;li&gt;a cache built for one response shape.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are all valid solutions. But they usually require the application to reconstruct the neighborhood every time it reads.&lt;/p&gt;

&lt;p&gt;KoutenDB asks a different question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if the database preserved useful locality when the data was written, so&lt;br&gt;
a later read could begin from that locality directly?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  A ring is a coordinate, not just a container
&lt;/h2&gt;

&lt;p&gt;KoutenDB stores a record with a coordinate-like &lt;code&gt;ring&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;users/123
users/123/orders
users/123/support
shops/1123
orders/A-001
products/sku-9/docs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The names are readable, but readability is not their main purpose. A ring is part of data placement and part of the read path.&lt;/p&gt;

&lt;p&gt;If the application starts from &lt;code&gt;users/123&lt;/code&gt;, KoutenDB can inspect that local hierarchy without beginning with an unrelated global collection. If it starts from &lt;code&gt;orders/A-001&lt;/code&gt;, it can use an order-centered view instead.&lt;/p&gt;

&lt;p&gt;This turns locality known by the application into retrieval information the database can retain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same data can be visible from another center
&lt;/h2&gt;

&lt;p&gt;Related context does not always fit one permanent hierarchy. An order belongs to a customer, a shop, and a product at the same time.&lt;/p&gt;

&lt;p&gt;KoutenDB therefore has a &lt;code&gt;stellar&lt;/code&gt; lens. It can attach existing rings to a useful center without copying their payloads.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kouten put &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;users&lt;/span&gt;/123 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{"kind":"user","name":"Alice"}'&lt;/span&gt; &lt;span class="nt"&gt;--codec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;json

kouten put &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;shops/1123 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{"kind":"shop","name":"Orbit Store"}'&lt;/span&gt; &lt;span class="nt"&gt;--codec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;json

kouten put &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;orders/A-001 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{"kind":"order","orderNo":"A-001","total":42}'&lt;/span&gt; &lt;span class="nt"&gt;--codec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;json

kouten stellar attach &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;commerce/order/A-001 &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;users&lt;/span&gt;/123

kouten stellar attach &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;commerce/order/A-001 &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;shops/1123

kouten stellar attach &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;commerce/order/A-001 &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;orders/A-001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the application can read from the order as the center:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kouten get &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;commerce/order/A-001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The original records remain in their original rings. Attaching or detaching a ring changes what the lens can see; it does not duplicate or delete the payload.&lt;/p&gt;

&lt;p&gt;This is useful when the same information needs to participate in several context views without turning each view into another copied document.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: retrieving useful information around a tourist destination
&lt;/h2&gt;

&lt;p&gt;Travel information makes the center-versus-boundary problem easier to see.&lt;/p&gt;

&lt;p&gt;Imagine that a visitor is looking at Kiyomizu-dera in Kyoto. The application knows the starting point, but a useful response probably should not contain only the temple record.&lt;/p&gt;

&lt;p&gt;The visitor may also need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;other nearby landmarks;&lt;/li&gt;
&lt;li&gt;restaurants and cafes;&lt;/li&gt;
&lt;li&gt;museums, galleries, and cultural facilities;&lt;/li&gt;
&lt;li&gt;events taking place that day;&lt;/li&gt;
&lt;li&gt;transit information;&lt;/li&gt;
&lt;li&gt;accessibility or opening-hour information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is no single permanent boundary for that context. A family, a solo traveler, and someone planning a rainy afternoon may need different parts of the same surrounding information.&lt;/p&gt;

&lt;p&gt;An importer or application can keep each place in a canonical ring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;landmarks/kyoto/kiyomizudera
landmarks/kyoto/yasaka-pagoda
restaurants/kyoto/gion
culture/kyoto/national-museum
events/kyoto/2026-07-22
transit/kyoto/higashiyama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can then attach the useful coordinates to an area-centered stellar lens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kouten stellar attach &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;landmarks/kyoto/kiyomizudera

kouten stellar attach &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;landmarks/kyoto/yasaka-pagoda

kouten stellar attach &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;restaurants/kyoto/gion

kouten stellar attach &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;culture/kyoto/national-museum

kouten stellar attach &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;events/kyoto/2026-07-22
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application can now begin with the Higashiyama area and retrieve the attached tourism context in one read:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kouten get &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or it can narrow the same view to restaurants or cultural facilities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kouten get &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="nt"&gt;--subring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;restaurants
kouten get &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;travel/kyoto/higashiyama &lt;span class="nt"&gt;--subring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;culture
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same restaurant can also be attached to a &lt;code&gt;travel/kyoto/rainy-day&lt;/code&gt; lens, a station-centered lens, or a day-plan lens without moving or copying its canonical payload.&lt;/p&gt;

&lt;p&gt;KoutenDB does not automatically infer geographic relevance from these names.&lt;br&gt;
The application, importer, or curation process still decides which coordinates belong in the neighborhood. The database's role is to preserve that decision and make it directly readable later.&lt;/p&gt;

&lt;p&gt;This is the intended meaning of surrounding information: the caller starts from a useful place, receives several categories of nearby context together, and can narrow the field of view without having to list every individual place in the request.&lt;/p&gt;
&lt;h2&gt;
  
  
  Is this just a path?
&lt;/h2&gt;

&lt;p&gt;A ring such as &lt;code&gt;landmarks/kyoto/kiyomizudera&lt;/code&gt; certainly looks like an ordinary path. KoutenDB deliberately uses readable hierarchical names because paths are a useful way to express parent and child locality.&lt;/p&gt;

&lt;p&gt;But a path by itself provides only hierarchy.&lt;/p&gt;

&lt;p&gt;If all tourism data lived under one tree, an application could read a prefix&lt;br&gt;
such as &lt;code&gt;travel/kyoto/higashiyama/*&lt;/code&gt;. That works when every useful relationship fits the same permanent hierarchy and the caller already knows which branches to request.&lt;/p&gt;

&lt;p&gt;The difficulty is that real data belongs to several contexts at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a restaurant belongs to its canonical restaurant catalog;&lt;/li&gt;
&lt;li&gt;geographically, it belongs to an area;&lt;/li&gt;
&lt;li&gt;operationally, it may belong to a currently open list;&lt;/li&gt;
&lt;li&gt;editorially, it may belong to a rainy-day guide;&lt;/li&gt;
&lt;li&gt;personally, it may belong to one visitor's itinerary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Duplicating the same record under every path creates synchronization and consistency work. Moving it into one path makes the other views harder to express. Storing only path strings leaves the application responsible for maintaining and joining all of those relationships.&lt;/p&gt;

&lt;p&gt;KoutenDB adds two things beyond the path syntax:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the ring hierarchy is understood by the retrieval engine and can be traversed with explicit depth, branch, filter, limit, sort, and projection controls.&lt;/li&gt;
&lt;li&gt;stellar metadata can connect rings from different hierarchies into another coordinate-centered view without changing their canonical paths or copying their payloads.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The stellar lens is therefore not another directory. It is a stored visibility relationship across existing coordinates.&lt;/p&gt;

&lt;p&gt;The same ring coordinate can also act as a boundary for authorization, dump/import, placement, and synchronization. A plain path string has none of those database semantics unless the application builds them separately.&lt;/p&gt;

&lt;p&gt;So the path is the readable address. The KoutenDB-specific part is how that address participates in placement, neighborhood retrieval, and reusable views across otherwise separate branches.&lt;/p&gt;
&lt;h2&gt;
  
  
  Not knowing the boundary does not mean an unbounded query
&lt;/h2&gt;

&lt;p&gt;"The caller does not know the exact boundary" should not mean "read&lt;br&gt;
everything."&lt;/p&gt;

&lt;p&gt;The caller still controls the field of view. KoutenDB can narrow a read with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a subring;&lt;/li&gt;
&lt;li&gt;hierarchy depth;&lt;/li&gt;
&lt;li&gt;branch budget;&lt;/li&gt;
&lt;li&gt;per-ring limits and sorting;&lt;/li&gt;
&lt;li&gt;filters;&lt;/li&gt;
&lt;li&gt;field selection;&lt;/li&gt;
&lt;li&gt;an overall result limit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, the same order-centered view can request only shop data or only a small projection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kouten get &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;commerce/order/A-001 &lt;span class="nt"&gt;--subring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;shops

kouten get &lt;span class="nt"&gt;--stellar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;commerce/order/A-001 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--selection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{ kind name orderNo total }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The distinction is important:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The application supplies a meaningful center and a cost boundary. It does&lt;br&gt;
not have to enumerate every record relationship that may form the answer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is why KoutenDB is intended for surrounding information rather than only exactly bounded queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not use a collection or partition key?
&lt;/h2&gt;

&lt;p&gt;Collections, namespaces, partitions, and shards can already reduce the amount of data a database examines.&lt;/p&gt;

&lt;p&gt;The difference is what they represent.&lt;/p&gt;

&lt;p&gt;A partition key commonly answers questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where is this record stored?&lt;/li&gt;
&lt;li&gt;Which node owns it?&lt;/li&gt;
&lt;li&gt;Which partition can be pruned?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;KoutenDB also wants locality to answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What information is likely to be useful around this record?&lt;/li&gt;
&lt;li&gt;Which nearby rings should enter the current field of view?&lt;/li&gt;
&lt;li&gt;Can the same existing ring become visible from another useful center?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes placement an application-visible retrieval concept, not only an internal scaling decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not begin with vector search?
&lt;/h2&gt;

&lt;p&gt;Vector search answers a valuable question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which items are semantically similar to this query?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But similarity is not the same as operational relevance.&lt;/p&gt;

&lt;p&gt;A customer's latest order, a permission record, and the applicable refund policy may be necessary context even when their embeddings are not the closest matches in a global corpus. Systems often compensate by adding namespaces and metadata filters before vector ranking.&lt;/p&gt;

&lt;p&gt;KoutenDB makes that first narrowing step the main data model:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;begin from a known user, order, tenant, topic, place, or time coordinate;&lt;/li&gt;
&lt;li&gt;open the useful local neighborhood;&lt;/li&gt;
&lt;li&gt;apply filters, vector ranking, reranking, or an LLM only to that smaller
working set when needed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Vectors remain useful. They are optional rather than the only way to discover related context.&lt;/p&gt;

&lt;p&gt;For local AI and RAG systems, that distinction can matter. The expensive work is not limited to the final LLM call. Loading candidates, comparing vectors, reranking chunks, transferring payloads, and filling a context window all have a cost. A smaller first-stage working set can reduce work throughout the pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not keep this entirely in application code?
&lt;/h2&gt;

&lt;p&gt;An application can maintain arrays of related IDs, write join tables, perform fan-out reads, and build cached response documents. Many applications already do.&lt;/p&gt;

&lt;p&gt;The tradeoff is that locality becomes scattered across code and supporting infrastructure. One rule determines reads, another determines authorization, another controls exports, and another decides how data should be copied or synchronized.&lt;/p&gt;

&lt;p&gt;KoutenDB's larger design goal is to let the same coordinate participate in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retrieval scope;&lt;/li&gt;
&lt;li&gt;authorization scope;&lt;/li&gt;
&lt;li&gt;dump and import boundaries;&lt;/li&gt;
&lt;li&gt;placement and compaction;&lt;/li&gt;
&lt;li&gt;delayed synchronization between topologies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The value is not just fewer lines in one query. It is keeping the application's concept of locality visible across the data lifecycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  The database cost should follow the working set
&lt;/h2&gt;

&lt;p&gt;Let the complete corpus contain &lt;code&gt;N&lt;/code&gt; records, while the useful neighborhood for one request contains &lt;code&gt;k&lt;/code&gt; records.&lt;/p&gt;

&lt;p&gt;Many systems eventually introduce a first-stage index or filter so later work does not operate over all &lt;code&gt;N&lt;/code&gt;. KoutenDB's central bet is that meaningful placement can provide part of that first stage directly.&lt;/p&gt;

&lt;p&gt;The goal is to make more of the request cost follow &lt;code&gt;k&lt;/code&gt;, the useful local working set, instead of repeatedly rediscovering locality from the full corpus.&lt;/p&gt;

&lt;p&gt;This is not an automatic performance guarantee. It depends on whether the application can express useful locality. If all queries are arbitrary and global, there may be no meaningful center to exploit.&lt;/p&gt;

&lt;p&gt;But many applications already begin with one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an authenticated user;&lt;/li&gt;
&lt;li&gt;a tenant;&lt;/li&gt;
&lt;li&gt;an order;&lt;/li&gt;
&lt;li&gt;a product;&lt;/li&gt;
&lt;li&gt;a project;&lt;/li&gt;
&lt;li&gt;a document group;&lt;/li&gt;
&lt;li&gt;a region;&lt;/li&gt;
&lt;li&gt;a service and time window;&lt;/li&gt;
&lt;li&gt;an entity in a simulation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;KoutenDB makes that starting knowledge part of the database query model.&lt;/p&gt;

&lt;h2&gt;
  
  
  When this model is useful
&lt;/h2&gt;

&lt;p&gt;KoutenDB is worth examining when all three of these statements are true:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;requests naturally begin from a known coordinate;&lt;/li&gt;
&lt;li&gt;the application frequently needs surrounding context, not only one exact
record;&lt;/li&gt;
&lt;li&gt;the useful context can be placed or attached meaningfully before it is
requested.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is less relevant when the main workload is arbitrary full-corpus analytics, global full-text search, independent lookup on every field, or strict relational constraints. Those problems already have databases built around them.&lt;/p&gt;

&lt;p&gt;The reason for another database is not that existing databases forgot how to look up records.&lt;/p&gt;

&lt;p&gt;It is that a growing class of application and AI requests does not begin with a complete description of the answer. It begins with a center.&lt;/p&gt;

&lt;p&gt;KoutenDB exists to make that center useful.&lt;/p&gt;

&lt;p&gt;The implementation, data-model demo, and reproducible benchmarks are available in the &lt;a href="https://github.com/puffball1567/koutendb" rel="noopener noreferrer"&gt;KoutenDB repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>database</category>
      <category>webdev</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>9 Databases Compared: PostgreSQL, MongoDB, Redis, and More</title>
      <dc:creator>puffball1567</dc:creator>
      <pubDate>Tue, 21 Jul 2026 16:22:06 +0000</pubDate>
      <link>https://dev.to/puffball1567/9-databases-compared-postgresql-mongodb-redis-and-more-4pkj</link>
      <guid>https://dev.to/puffball1567/9-databases-compared-postgresql-mongodb-redis-and-more-4pkj</guid>
      <description>&lt;p&gt;Choosing a database can feel harder than it needs to be.&lt;/p&gt;

&lt;p&gt;This beginner-friendly database comparison covers PostgreSQL, MySQL, SQLite, MongoDB, Redis, ClickHouse, OpenSearch, Qdrant, and KoutenDB. The goal is to help you decide which database fits your application—not to declare one winner.&lt;/p&gt;

&lt;p&gt;Should you use PostgreSQL or MySQL? Is MongoDB easier for JSON? Is Redis only a cache? Do you need a vector database for RAG? And where do newer database ideas fit?&lt;/p&gt;

&lt;p&gt;There is no single "best database." A better question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What kind of work does this database make simple?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This guide introduces nine databases without trying to rank them. Each one has a different center of gravity, and many real systems use more than one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Database&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Strongest fit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PostgreSQL&lt;/td&gt;
&lt;td&gt;Relational SQL&lt;/td&gt;
&lt;td&gt;General-purpose applications and complex data relationships&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;td&gt;Relational SQL&lt;/td&gt;
&lt;td&gt;Mainstream web applications and widely supported hosting stacks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQLite&lt;/td&gt;
&lt;td&gt;Embedded relational SQL&lt;/td&gt;
&lt;td&gt;Local applications and simple single-file storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;Document database&lt;/td&gt;
&lt;td&gt;JSON-like documents and evolving data shapes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redis&lt;/td&gt;
&lt;td&gt;Data structure store&lt;/td&gt;
&lt;td&gt;Caching, sessions, counters, streams, and low-latency state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ClickHouse&lt;/td&gt;
&lt;td&gt;Column-oriented SQL / OLAP&lt;/td&gt;
&lt;td&gt;Analytics over large event and log datasets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenSearch&lt;/td&gt;
&lt;td&gt;Search and analytics engine&lt;/td&gt;
&lt;td&gt;Full-text search, log exploration, and observability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qdrant&lt;/td&gt;
&lt;td&gt;Vector database&lt;/td&gt;
&lt;td&gt;Semantic similarity search, recommendations, and RAG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KoutenDB&lt;/td&gt;
&lt;td&gt;Coordinate-local document/vector database&lt;/td&gt;
&lt;td&gt;Related context around a useful starting point&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  1. PostgreSQL: A Strong General-Purpose Default
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best at:&lt;/strong&gt; relational data, transactions, data integrity, and complex SQL.&lt;/p&gt;

&lt;p&gt;PostgreSQL is a mature object-relational database with ACID transactions, foreign keys, many index types, JSON support, full-text search, replication, and a large extension ecosystem. Its ability to model relationships and enforce rules inside the database makes it a strong starting point for many&lt;br&gt;
applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good fit for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SaaS products;&lt;/li&gt;
&lt;li&gt;business systems;&lt;/li&gt;
&lt;li&gt;financial and inventory data;&lt;/li&gt;
&lt;li&gt;applications with joins and reporting;&lt;/li&gt;
&lt;li&gt;teams that want one capable general-purpose database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind:&lt;/strong&gt; A specialized cache, search engine, vector database, or OLAP system may still be useful beside PostgreSQL when one workload becomes large or specialized.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.postgresql.org/about/" rel="noopener noreferrer"&gt;PostgreSQL overview&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. MySQL: A Familiar Choice for Web Applications
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best at:&lt;/strong&gt; conventional relational workloads with broad hosting, tooling, and framework support.&lt;/p&gt;

&lt;p&gt;MySQL is a relational SQL database with a long history in web development. It is widely supported by hosting providers, CMS platforms, application frameworks, and language libraries. That familiarity can reduce adoption and operations work for a small team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good fit for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;web applications;&lt;/li&gt;
&lt;li&gt;ecommerce and CMS systems;&lt;/li&gt;
&lt;li&gt;APIs built on an existing MySQL stack;&lt;/li&gt;
&lt;li&gt;teams with MySQL operational experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind:&lt;/strong&gt; The PostgreSQL-versus-MySQL decision is rarely solved by a single feature checklist. Existing team knowledge, hosting, extensions, and application requirements often matter more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.mysql.com/doc/refman/en/what-is-mysql.html" rel="noopener noreferrer"&gt;MySQL overview&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. SQLite: A Database Without a Server
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best at:&lt;/strong&gt; embedded, local, and single-file SQL storage.&lt;/p&gt;

&lt;p&gt;SQLite runs inside the application process. It has no separate database server to deploy, and a complete database can live in one portable file. Despite its small footprint, it supports transactions, tables, indexes, triggers, and views.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good fit for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mobile and desktop applications;&lt;/li&gt;
&lt;li&gt;command-line tools;&lt;/li&gt;
&lt;li&gt;local-first software;&lt;/li&gt;
&lt;li&gt;tests and prototypes;&lt;/li&gt;
&lt;li&gt;small services with a simple deployment model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind:&lt;/strong&gt; If many machines or remote clients need to write concurrently, a client/server database may be a better operational fit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.sqlite.org/about.html" rel="noopener noreferrer"&gt;SQLite overview&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. MongoDB: Documents That Look Like Application Data
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best at:&lt;/strong&gt; storing JSON-like documents with nested objects and arrays.&lt;/p&gt;

&lt;p&gt;MongoDB stores records as BSON documents. This often maps naturally to objects already used by web applications and APIs. Related fields can be embedded in one document, while collections and indexes provide larger-scale organization and access paths.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good fit for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;content and catalog data;&lt;/li&gt;
&lt;li&gt;applications with nested documents;&lt;/li&gt;
&lt;li&gt;rapidly evolving data shapes;&lt;/li&gt;
&lt;li&gt;systems where a document is the natural unit of access.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind:&lt;/strong&gt; A flexible document model does not remove the need for data modeling. Relationships, document growth, indexes, and consistency boundaries still need deliberate design.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/core/document/" rel="noopener noreferrer"&gt;MongoDB document model&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Redis: Fast Access to Useful Data Structures
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best at:&lt;/strong&gt; low-latency access to keys, counters, sets, lists, streams, and other data structures.&lt;/p&gt;

&lt;p&gt;Redis is often introduced as a cache, but it can also be used as a database, streaming engine, and message broker. Its commands make common operations such as incrementing a counter, expiring a session, maintaining a ranking, or publishing an event straightforward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good fit for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;caching;&lt;/li&gt;
&lt;li&gt;sessions and rate limits;&lt;/li&gt;
&lt;li&gt;counters and leaderboards;&lt;/li&gt;
&lt;li&gt;queues, streams, and pub/sub;&lt;/li&gt;
&lt;li&gt;temporary or frequently accessed state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind:&lt;/strong&gt; Decide explicitly how persistence, recovery, memory use, and eviction should work before treating Redis as the only source of truth.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://redis.io/docs/latest/develop/get-started/" rel="noopener noreferrer"&gt;Redis overview&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. ClickHouse: Analytics Across Large Datasets
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best at:&lt;/strong&gt; fast analytical queries over large numbers of rows.&lt;/p&gt;

&lt;p&gt;ClickHouse is a column-oriented SQL database designed for online analytical processing (OLAP). Column-oriented storage is well suited to queries that scan a few fields across many records and calculate aggregates such as counts, totals, percentiles, or time-series summaries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good fit for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;product and business analytics;&lt;/li&gt;
&lt;li&gt;logs, events, and traces;&lt;/li&gt;
&lt;li&gt;large reporting datasets;&lt;/li&gt;
&lt;li&gt;real-time analytical dashboards.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind:&lt;/strong&gt; ClickHouse is centered on analytical workloads. A traditional transactional database is usually easier for ordinary row-by-row application updates and relationship-heavy OLTP flows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://clickhouse.com/docs/intro" rel="noopener noreferrer"&gt;ClickHouse overview&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7. OpenSearch: Search, Logs, and Observability
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best at:&lt;/strong&gt; full-text search and exploration across indexed data.&lt;/p&gt;

&lt;p&gt;OpenSearch provides a search and analytics engine together with APIs and dashboards. It supports text search, Query DSL, index management, aggregations, vector search, and observability-oriented workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good fit for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;site and product search;&lt;/li&gt;
&lt;li&gt;log search;&lt;/li&gt;
&lt;li&gt;application and infrastructure observability;&lt;/li&gt;
&lt;li&gt;relevance-based text retrieval;&lt;/li&gt;
&lt;li&gt;dashboards over indexed events.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind:&lt;/strong&gt; OpenSearch commonly works beside a primary application database. The indexing pipeline, cluster sizing, mappings, and lifecycle of duplicated search data become part of the system design.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.opensearch.org/latest/about/" rel="noopener noreferrer"&gt;OpenSearch documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Qdrant: Similarity Search for Vectors
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best at:&lt;/strong&gt; finding items that are similar in embedding space.&lt;/p&gt;

&lt;p&gt;Qdrant organizes data into collections of points. Each point can contain one or more vectors plus payload metadata. Its vector indexes and filtering support make it suitable for semantic retrieval where exact keywords are not enough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good fit for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;semantic search;&lt;/li&gt;
&lt;li&gt;recommendations;&lt;/li&gt;
&lt;li&gt;image, audio, or document similarity;&lt;/li&gt;
&lt;li&gt;retrieval-augmented generation (RAG);&lt;/li&gt;
&lt;li&gt;vector search combined with metadata filters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind:&lt;/strong&gt; A vector database solves a specific retrieval problem. You still need to choose embedding models, evaluate relevance, design metadata, and plan memory and storage as collections grow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://qdrant.tech/documentation/overview/" rel="noopener noreferrer"&gt;Qdrant overview&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9. KoutenDB: Related Data Around a Starting Point
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best at:&lt;/strong&gt; retrieving a useful neighborhood of related data from a starting coordinate, even when the caller does not know the exact result boundary in advance.&lt;/p&gt;

&lt;p&gt;KoutenDB is a ring-oriented NoSQL document/vector database written in Nim. A &lt;code&gt;ring&lt;/code&gt; is not only a label: it is part of data placement and the read path.&lt;br&gt;
Applications can place related data into nearby rings or attach existing rings to a &lt;code&gt;stellar&lt;/code&gt; lens. A read can start from a user, order, product, topic, or other coordinate and bring nearby parent, child, sibling, or attached rings into the same field of view.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good fit for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;surrounding context for a user, order, product, tenant, or topic;&lt;/li&gt;
&lt;li&gt;related-data bundles for application APIs without enumerating every record;&lt;/li&gt;
&lt;li&gt;knowledge retrieval where the useful neighborhood is known more clearly than its exact boundary;&lt;/li&gt;
&lt;li&gt;reducing candidates before vector ranking or an LLM step;&lt;/li&gt;
&lt;li&gt;experiments with locality-aware storage and retrieval.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What makes it different:&lt;/strong&gt; KoutenDB does not require the caller to know the final boundary of the query. It needs a useful center. A stellar read follows the configured coordinate neighborhood, while depth, branch budget, subring, limit, and sort options control the field of view. Its central question is:&lt;br&gt;
"What useful information lives around this point?"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb" rel="noopener noreferrer"&gt;KoutenDB repository&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Database Should You Use?
&lt;/h2&gt;

&lt;p&gt;If you are still unsure, start with the main job your database needs to do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;General relational application:&lt;/strong&gt; PostgreSQL or MySQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded or local SQL:&lt;/strong&gt; SQLite&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON-like document storage:&lt;/strong&gt; MongoDB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache and low-latency shared state:&lt;/strong&gt; Redis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large-scale analytics:&lt;/strong&gt; ClickHouse&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full-text and log search:&lt;/strong&gt; OpenSearch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vector similarity search:&lt;/strong&gt; Qdrant&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Related context around a useful starting coordinate:&lt;/strong&gt; KoutenDB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These choices are not mutually exclusive. A product might use PostgreSQL as its primary database, Redis for caching, OpenSearch for text search, and Qdrant for semantic retrieval. Another application may need only SQLite. A system whose data forms meaningful neighborhoods around users, orders, products, topics,&lt;br&gt;
regions, or points in time may want to explore KoutenDB's locality model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is the best database for a small SaaS application?
&lt;/h3&gt;

&lt;p&gt;PostgreSQL and MySQL are both strong starting points for a conventional SaaS backend. They provide transactions, constraints, indexes, and mature operations without requiring several specialized databases on day one. Add another system only after a real cache, search, analytics, or retrieval bottleneck appears.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which database should I use for a small or local project?
&lt;/h3&gt;

&lt;p&gt;SQLite is often the simplest choice when the application runs locally and does not need a separate database server. For a server application used by multiple people or services, PostgreSQL or MySQL may provide an easier growth path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which database should I use for JSON data?
&lt;/h3&gt;

&lt;p&gt;MongoDB is a natural candidate when the document is the main unit of storage and retrieval. PostgreSQL is also worth considering when JSON data must live beside relational data, transactions, and SQL queries. Choose from the access pattern, not only from the format of the incoming API payload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which database is best for caching and user sessions?
&lt;/h3&gt;

&lt;p&gt;Redis is a common fit for caches, expiring sessions, counters, rate limits, and other short-lived shared state. A relational or document database can remain the durable source of truth while Redis serves the frequently accessed path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I use ClickHouse or OpenSearch for logs?
&lt;/h3&gt;

&lt;p&gt;Choose ClickHouse when SQL analytics and aggregation across large event sets are central. Choose OpenSearch when text search, relevance, interactive log exploration, and search-oriented dashboards are central. Some observability systems use both, but that additional complexity should solve a real need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which database should I use for RAG and vector search?
&lt;/h3&gt;

&lt;p&gt;Qdrant is designed around vector similarity, payload filtering, and semantic retrieval. OpenSearch can combine text and vector search, while PostgreSQL can gain vector capabilities through extensions. KoutenDB addresses a different part of the problem: it can start from a useful coordinate, retrieve the nearby context, and reduce the candidate set before vector ranking or an LLM step. The caller does not need to know the exact final context boundary in advance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which database fits user-centered or multi-tenant related data?
&lt;/h3&gt;

&lt;p&gt;PostgreSQL and MySQL commonly model tenants and users with keys, constraints, and indexes. KoutenDB is designed for reads that start from a coordinate such as &lt;code&gt;tenant/acme&lt;/code&gt; or &lt;code&gt;users/123&lt;/code&gt;, then bring nearby profile, orders, billing, or other attached information into view. The application supplies the center; it does not have to enumerate the complete result boundary first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does an application need more than one database?
&lt;/h3&gt;

&lt;p&gt;Not necessarily. Starting with one general-purpose database keeps operations simple. Add Redis, OpenSearch, Qdrant, ClickHouse, KoutenDB, or another specialized system only when a clear workload justifies the additional moving parts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;Do not choose a database only because it wins a benchmark or appears in a popular architecture diagram. Ask a few practical questions first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does the application know before it starts a query?&lt;/li&gt;
&lt;li&gt;Are relationships, documents, vectors, text, or aggregates the main shape?&lt;/li&gt;
&lt;li&gt;Which consistency and durability guarantees are required?&lt;/li&gt;
&lt;li&gt;How much operational complexity can the team support?&lt;/li&gt;
&lt;li&gt;How will the data be exported or migrated later?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best database is usually the one that makes your important access patterns simple, predictable, and maintainable.&lt;/p&gt;

</description>
      <category>database</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>KoutenDB v0.8.0: A Full Public-Surface Migration</title>
      <dc:creator>puffball1567</dc:creator>
      <pubDate>Mon, 20 Jul 2026 09:04:18 +0000</pubDate>
      <link>https://dev.to/puffball1567/koutendb-v080-a-full-public-surface-migration-2ocj</link>
      <guid>https://dev.to/puffball1567/koutendb-v080-a-full-public-surface-migration-2ocj</guid>
      <description>&lt;p&gt;I released &lt;strong&gt;KoutenDB v0.8.0&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Release:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb/releases/tag/v0.8.0" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb/releases/tag/v0.8.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This release is different from v0.7.0. The previous release focused on storage,&lt;br&gt;
transport, recovery, authorization, and operational hardening. v0.8.0 carries&lt;br&gt;
that work forward under the project's new active name: &lt;strong&gt;KoutenDB&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is primarily a naming and migration release, not a new storage-engine&lt;br&gt;
feature release. However, the migration reaches across the complete public&lt;br&gt;
surface, so it is more than changing the title in the README.&lt;/p&gt;
&lt;h2&gt;
  
  
  The v0.7.0 to v0.8.0 Diff
&lt;/h2&gt;

&lt;p&gt;The Git diff between the two release tags reports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;188 changed files&lt;/li&gt;
&lt;li&gt;3,970 insertions&lt;/li&gt;
&lt;li&gt;4,203 deletions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of that volume is rename churn. Source modules, tests, examples, scripts,&lt;br&gt;
documentation, CI, headers, and driver foundations all had to move together.&lt;/p&gt;

&lt;p&gt;The high-level difference is:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;v0.7.0&lt;/th&gt;
&lt;th&gt;v0.8.0&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Project&lt;/td&gt;
&lt;td&gt;RocheDB&lt;/td&gt;
&lt;td&gt;KoutenDB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nim package/module&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rochedb&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;koutendb&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;roche&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kouten&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daemon&lt;/td&gt;
&lt;td&gt;&lt;code&gt;roched&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;koutend&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C ABI library&lt;/td&gt;
&lt;td&gt;&lt;code&gt;librochedb.so&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;libkoutendb.so&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C header&lt;/td&gt;
&lt;td&gt;&lt;code&gt;include/rochedb.h&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;include/koutendb.h&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C symbol prefix&lt;/td&gt;
&lt;td&gt;&lt;code&gt;roche_*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kouten_*&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repository&lt;/td&gt;
&lt;td&gt;&lt;code&gt;puffball1567/rochedb&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;puffball1567/koutendb&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Configuration names and build variables were migrated to the &lt;code&gt;KOUTEN_*&lt;/code&gt; and&lt;br&gt;
&lt;code&gt;KOUTENDB_*&lt;/code&gt; families as well.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why KoutenDB?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Kouten&lt;/code&gt; comes from the Japanese word &lt;em&gt;kouten&lt;/em&gt; (公転), meaning orbital&lt;br&gt;
revolution: one body moving around another.&lt;/p&gt;

&lt;p&gt;That meaning matches the database model. KoutenDB treats rings,&lt;br&gt;
orbit-inspired placement, and locality as part of retrieval. When an&lt;br&gt;
application has a meaningful locality boundary, the database can use it to&lt;br&gt;
reduce unrelated reads, transferred bytes, candidate memory, and downstream&lt;br&gt;
AI/RAG or application work.&lt;/p&gt;

&lt;p&gt;The name changed, but this technical direction did not.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Migration Reaches the Whole Public Surface
&lt;/h2&gt;

&lt;p&gt;For Nim users, new code should import &lt;code&gt;koutendb&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nim"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;koutendb&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;koutendb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"""{"title":"Hello"}"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"docs/japan"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Command-line examples now use &lt;code&gt;kouten&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kouten put &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;docs/japan &lt;span class="nt"&gt;--payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{"title":"Hello"}'&lt;/span&gt;
kouten get &lt;span class="nt"&gt;--ring&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;docs/japan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Server processes now use &lt;code&gt;koutend&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;koutend &lt;span class="nt"&gt;--id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="nt"&gt;--peers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;h1:7301,h2:7301,h3:7301 &lt;span class="nt"&gt;--data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/var/lib/kouten
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The C ABI migration is intentionally explicit. Consumers should include&lt;br&gt;
&lt;code&gt;include/koutendb.h&lt;/code&gt;, link against &lt;code&gt;libkoutendb.so&lt;/code&gt;, and call the &lt;code&gt;kouten_*&lt;/code&gt;&lt;br&gt;
symbols. This keeps the public native boundary internally consistent, but it&lt;br&gt;
also means existing C ABI consumers need to update and rebuild.&lt;/p&gt;
&lt;h2&gt;
  
  
  Drivers and Package Names
&lt;/h2&gt;

&lt;p&gt;The driver-facing names were migrated too. Published packages now use the&lt;br&gt;
KoutenDB name for Rust, JavaScript/TypeScript, PHP, Python, and C++ distribution&lt;br&gt;
paths, while the in-repository C#, Go, Kotlin, Node, PHP, Swift, and C++&lt;br&gt;
foundations were updated to the same naming scheme.&lt;/p&gt;

&lt;p&gt;One structural cleanup is also part of the v0.7.0 to v0.8.0 diff: the old&lt;br&gt;
in-repository Python driver was removed from the core repository. Python support&lt;br&gt;
continues as a separately maintained and published native TCP driver:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb-python" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb-python&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This avoids keeping two copies of the Python implementation in different&lt;br&gt;
release flows.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Did Not Change?
&lt;/h2&gt;

&lt;p&gt;KoutenDB remains a technical preview and research OSS project. Its core thesis&lt;br&gt;
is still:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use meaningful placement to reduce the amount of data that must be read,&lt;br&gt;
transferred, held in memory, and passed to downstream systems.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The ring-oriented NoSQL document/vector model, locality-aware retrieval goal,&lt;br&gt;
and smaller-working-set focus continue from v0.7.0. v0.8.0 does not claim a new&lt;br&gt;
benchmark result or a new storage-engine capability merely because the code&lt;br&gt;
diff is large.&lt;/p&gt;
&lt;h2&gt;
  
  
  Migration Quickstart
&lt;/h2&gt;

&lt;p&gt;For a new Nim installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nimble &lt;span class="nb"&gt;install &lt;/span&gt;koutendb
kouten &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To build from source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/puffball1567/koutendb.git
&lt;span class="nb"&gt;cd &lt;/span&gt;koutendb
nimble check
scripts/test_all_smoke.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Existing integrations should check these areas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Nim imports and package dependencies&lt;/li&gt;
&lt;li&gt;CLI and daemon command names&lt;/li&gt;
&lt;li&gt;environment and configuration variable names&lt;/li&gt;
&lt;li&gt;C headers, shared-library names, and symbol prefixes&lt;/li&gt;
&lt;li&gt;driver package and repository URLs&lt;/li&gt;
&lt;li&gt;documentation and CI scripts that contain the previous names&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Verification
&lt;/h2&gt;

&lt;p&gt;The v0.8.0 rename was checked across the core Nim modules, CLI, daemon, C ABI,&lt;br&gt;
core tests, CLI CRUD smoke tests, TLS-enabled C ABI tests, driver compatibility,&lt;br&gt;
and the complete smoke suite. The rename PR also passed the Linux and macOS C&lt;br&gt;
ABI jobs in GitHub Actions.&lt;/p&gt;

&lt;p&gt;KoutenDB v0.8.0 is available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>opensource</category>
      <category>ai</category>
      <category>nosql</category>
    </item>
    <item>
      <title>RocheDB Is Now KoutenDB</title>
      <dc:creator>puffball1567</dc:creator>
      <pubDate>Mon, 20 Jul 2026 08:51:32 +0000</pubDate>
      <link>https://dev.to/puffball1567/rochedb-is-now-koutendb-3bka</link>
      <guid>https://dev.to/puffball1567/rochedb-is-now-koutendb-3bka</guid>
      <description>&lt;p&gt;&lt;strong&gt;RocheDB has been renamed to KoutenDB.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the main change in &lt;strong&gt;KoutenDB v0.8.0&lt;/strong&gt;, a naming and migration release.&lt;br&gt;
The technical direction is unchanged: KoutenDB remains a ring-oriented NoSQL&lt;br&gt;
document and vector store focused on locality-aware retrieval and smaller&lt;br&gt;
working sets.&lt;/p&gt;

&lt;p&gt;Release:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb/releases/tag/v0.8.0" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb/releases/tag/v0.8.0&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why KoutenDB?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Kouten&lt;/code&gt; comes from the Japanese word &lt;em&gt;kouten&lt;/em&gt; (公転), meaning orbital&lt;br&gt;
revolution: one body moving around another.&lt;/p&gt;

&lt;p&gt;The name fits the database model more directly. KoutenDB uses rings and&lt;br&gt;
orbit-inspired placement as part of the retrieval path. Its goal is to use&lt;br&gt;
meaningful locality to reduce unrelated reads, transferred bytes, candidate&lt;br&gt;
memory, and downstream AI/RAG or application work.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Changed?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Project name: &lt;strong&gt;KoutenDB&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Nim package: &lt;code&gt;koutendb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;CLI: &lt;code&gt;kouten&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Daemon: &lt;code&gt;koutend&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;C ABI library: &lt;code&gt;libkoutendb.so&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;C header: &lt;code&gt;include/koutendb.h&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;C ABI symbol prefix: &lt;code&gt;kouten_*&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Repository: &lt;a href="https://github.com/puffball1567/koutendb" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The documentation and examples have also been updated to use the KoutenDB&lt;br&gt;
naming scheme.&lt;/p&gt;
&lt;h2&gt;
  
  
  Migrating
&lt;/h2&gt;

&lt;p&gt;For new Nim installations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nimble &lt;span class="nb"&gt;install &lt;/span&gt;koutendb
kouten &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To work from source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/puffball1567/koutendb.git
&lt;span class="nb"&gt;cd &lt;/span&gt;koutendb
nimble check
scripts/test_all_smoke.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;C ABI users should now include &lt;code&gt;include/koutendb.h&lt;/code&gt;, link against&lt;br&gt;
&lt;code&gt;libkoutendb.so&lt;/code&gt;, and use the &lt;code&gt;kouten_*&lt;/code&gt; symbol family.&lt;/p&gt;

&lt;p&gt;Older names may remain visible temporarily in historical posts and archived&lt;br&gt;
package entries, but &lt;strong&gt;KoutenDB&lt;/strong&gt; is now the active project, package, CLI, and&lt;br&gt;
repository name.&lt;/p&gt;

&lt;p&gt;Thank you to everyone who has followed the project so far. Development will&lt;br&gt;
continue at:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>opensource</category>
      <category>nim</category>
      <category>devlog</category>
    </item>
    <item>
      <title>KoutenDB: Data Locality as a First-Stage Retrieval Index</title>
      <dc:creator>puffball1567</dc:creator>
      <pubDate>Sat, 18 Jul 2026 04:20:32 +0000</pubDate>
      <link>https://dev.to/puffball1567/rochedb-data-locality-as-a-first-stage-retrieval-index-237k</link>
      <guid>https://dev.to/puffball1567/rochedb-data-locality-as-a-first-stage-retrieval-index-237k</guid>
      <description>&lt;p&gt;One of the ideas behind &lt;strong&gt;KoutenDB&lt;/strong&gt; is easy to miss if we describe it only as a&lt;br&gt;
NoSQL database, a document store, or a vector-aware storage engine for AI and&lt;br&gt;
search workloads.&lt;/p&gt;

&lt;p&gt;The stronger idea is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Data locality and data placement can become the first stage of retrieval.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In many databases and search systems, storage and indexing are treated as&lt;br&gt;
separate layers. Data is stored somewhere, then database indexes, inverted&lt;br&gt;
indexes, or vector indexes are built on top of it so that queries can find it&lt;br&gt;
later.&lt;/p&gt;

&lt;p&gt;KoutenDB tries to push part of that work into placement.&lt;/p&gt;

&lt;p&gt;If related data is written into nearby rings, stellar neighborhoods, or&lt;br&gt;
application-defined locality groups, then the first retrieval question changes&lt;br&gt;
from:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which global index should I search?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which local region of the data should I open first?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That difference matters for search infrastructure, recommendation systems, RAG&lt;br&gt;
systems, LLM context stores, vector search pipelines, and large&lt;br&gt;
retrieval-heavy applications.&lt;/p&gt;

&lt;p&gt;For teams operating large-scale retrieval systems, this is close to several&lt;br&gt;
daily engineering problems: candidate generation, candidate pruning, I/O&lt;br&gt;
amplification, memory pressure, cache locality, and tail latency before the&lt;br&gt;
ranking pipeline even starts.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ranking is not the first problem
&lt;/h2&gt;

&lt;p&gt;Search systems often discuss ranking algorithms and retrieval techniques:&lt;br&gt;
PageRank, BM25, vector similarity, freshness, authority signals,&lt;br&gt;
personalization, semantic search, reranking, and many other scoring methods.&lt;/p&gt;

&lt;p&gt;Those are important.&lt;/p&gt;

&lt;p&gt;But before ranking, a search or RAG pipeline has to decide what data even&lt;br&gt;
deserves to be examined.&lt;/p&gt;

&lt;p&gt;A simplified search, recommendation, or RAG retrieval pipeline looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Decide which data region to inspect.&lt;/li&gt;
&lt;li&gt;Generate and prune candidate records.&lt;/li&gt;
&lt;li&gt;Score or rank those candidates.&lt;/li&gt;
&lt;li&gt;Rerank, summarize, or pass selected context downstream.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;KoutenDB focuses on the first two stages.&lt;/p&gt;

&lt;p&gt;It does not try to replace ranking algorithms. Instead, it tries to reduce how&lt;br&gt;
much unrelated data those algorithms, vector search systems, or LLM rerankers&lt;br&gt;
need to see.&lt;/p&gt;

&lt;p&gt;If the candidate set is already narrow and relevant, later ranking work becomes&lt;br&gt;
lighter. In a multi-stage ranking system, reducing weak candidates before the&lt;br&gt;
first ranking stage can also reduce downstream reranking cost and tail latency.&lt;/p&gt;
&lt;h2&gt;
  
  
  Data placement as an index-like structure
&lt;/h2&gt;

&lt;p&gt;Traditional database and search indexes are usually separate structures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a B-tree;&lt;/li&gt;
&lt;li&gt;a secondary index;&lt;/li&gt;
&lt;li&gt;an inverted index for full-text search;&lt;/li&gt;
&lt;li&gt;an ANN index for vector search;&lt;/li&gt;
&lt;li&gt;a materialized lookup table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those structures are useful, and KoutenDB is not arguing that they should&lt;br&gt;
disappear.&lt;/p&gt;

&lt;p&gt;But KoutenDB adds another retrieval layer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The physical and logical location of the data is also retrieval information.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A ring is not just a collection label. A ring says where the data belongs and&lt;br&gt;
where future search, RAG, or application reads should probably begin.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web/github/nim/koutendb/page
web/github/nim/koutendb/keywords
web/github/nim/koutendb/summary
web/github/nim/koutendb/links
web/github/nim/koutendb/embedding
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These records are not merely stored under similar names. They are intentionally&lt;br&gt;
near each other because a search or RAG request about KoutenDB, Nim, or the&lt;br&gt;
project's documentation may need them together.&lt;/p&gt;

&lt;p&gt;That means the storage layout is already doing part of the candidate-selection,&lt;br&gt;
candidate-pruning, and working-set reduction work.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why this helps search engines and retrieval systems
&lt;/h2&gt;

&lt;p&gt;Imagine a search engine, recommendation system, or AI search system that has&lt;br&gt;
already collected pages, links, summaries, keywords, embeddings, entity hints,&lt;br&gt;
language metadata, region metadata, and freshness information.&lt;/p&gt;

&lt;p&gt;One approach is to store those pieces separately and repeatedly join or look up&lt;br&gt;
the metadata needed for ranking, semantic search, or retrieval augmentation.&lt;/p&gt;

&lt;p&gt;Another approach is to keep related pieces close enough that the system can&lt;br&gt;
open a local region first, generate a smaller candidate set, and then rank what&lt;br&gt;
it finds there.&lt;/p&gt;

&lt;p&gt;KoutenDB is designed for the second approach.&lt;/p&gt;

&lt;p&gt;The goal is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Replace PageRank.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The goal is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Give PageRank, BM25, vector search, semantic ranking, and rerankers less&lt;br&gt;
unrelated data to inspect.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If unrelated candidates are not placed near the query's natural locality, they&lt;br&gt;
do not have to be opened first.&lt;/p&gt;

&lt;p&gt;That can reduce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;records scanned;&lt;/li&gt;
&lt;li&gt;payloads loaded into memory;&lt;/li&gt;
&lt;li&gt;bytes transferred between services;&lt;/li&gt;
&lt;li&gt;I/O amplification;&lt;/li&gt;
&lt;li&gt;cache misses around unrelated data;&lt;/li&gt;
&lt;li&gt;ranking and reranking work;&lt;/li&gt;
&lt;li&gt;multi-stage ranking pressure;&lt;/li&gt;
&lt;li&gt;tail latency from wide candidate reads;&lt;/li&gt;
&lt;li&gt;downstream LLM context size;&lt;/li&gt;
&lt;li&gt;cache pressure;&lt;/li&gt;
&lt;li&gt;repeated lookup or join-style work around related metadata.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Why this helps RAG optimization and LLM context management
&lt;/h2&gt;

&lt;p&gt;RAG systems and LLM applications are especially sensitive to candidate volume.&lt;/p&gt;

&lt;p&gt;Even if the final answer only needs a few passages, the system may spend work&lt;br&gt;
on many documents before that point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retrieving candidates;&lt;/li&gt;
&lt;li&gt;loading document chunks;&lt;/li&gt;
&lt;li&gt;holding payloads in memory;&lt;/li&gt;
&lt;li&gt;computing or comparing embeddings;&lt;/li&gt;
&lt;li&gt;reranking;&lt;/li&gt;
&lt;li&gt;trimming context;&lt;/li&gt;
&lt;li&gt;sending text into an LLM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If placement can reduce the candidate set before those steps, the savings are&lt;br&gt;
not limited to database read latency. They can propagate through the rest of&lt;br&gt;
the retrieval pipeline, reranking pipeline, and LLM serving path.&lt;/p&gt;

&lt;p&gt;This is why KoutenDB's locality model is not only a storage concern. It is also&lt;br&gt;
an AI efficiency concern.&lt;/p&gt;

&lt;p&gt;In a RAG workload, reading less unrelated data can mean fewer tokens, less&lt;br&gt;
reranking work, smaller LLM context windows, less memory pressure, and lower&lt;br&gt;
LLM serving cost.&lt;/p&gt;
&lt;h2&gt;
  
  
  This is different from ordinary partitioning
&lt;/h2&gt;

&lt;p&gt;At first glance, rings may look like database partitioning or sharding.&lt;/p&gt;

&lt;p&gt;There is overlap, but KoutenDB is trying to use the idea more broadly.&lt;/p&gt;

&lt;p&gt;Partitioning or sharding usually answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which shard or partition owns this data?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;KoutenDB rings and stellar neighborhoods also answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which nearby data is likely to be useful with this data?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That second question is the important one.&lt;/p&gt;

&lt;p&gt;For search, recommendation, RAG, and vector retrieval, the expensive part is&lt;br&gt;
often not finding one exact row. It is candidate generation and candidate&lt;br&gt;
pruning: finding a useful local neighborhood without opening a large amount of&lt;br&gt;
weakly related data.&lt;/p&gt;
&lt;h2&gt;
  
  
  Not a replacement for analytical warehouses
&lt;/h2&gt;

&lt;p&gt;This does not mean KoutenDB should replace BigQuery, Snowflake, ClickHouse, or&lt;br&gt;
other analytical systems.&lt;/p&gt;

&lt;p&gt;Large cross-dataset aggregation is a different problem. If the task is to scan&lt;br&gt;
massive historical data and compute arbitrary analytics, a columnar warehouse&lt;br&gt;
or analytics engine is the right tool.&lt;/p&gt;

&lt;p&gt;KoutenDB is aimed at operational databases, search backends, recommendation&lt;br&gt;
systems, RAG infrastructure, and retrieval-heavy paths where the application&lt;br&gt;
already knows meaningful locality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user;&lt;/li&gt;
&lt;li&gt;tenant;&lt;/li&gt;
&lt;li&gt;topic;&lt;/li&gt;
&lt;li&gt;region;&lt;/li&gt;
&lt;li&gt;source;&lt;/li&gt;
&lt;li&gt;document group;&lt;/li&gt;
&lt;li&gt;project;&lt;/li&gt;
&lt;li&gt;time window;&lt;/li&gt;
&lt;li&gt;search context;&lt;/li&gt;
&lt;li&gt;RAG corpus segment;&lt;/li&gt;
&lt;li&gt;vector-search namespace;&lt;/li&gt;
&lt;li&gt;LLM memory or context boundary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In those paths, many "aggregate", "related data", or "context retrieval" reads&lt;br&gt;
can be reduced to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Read this ring or nearby neighborhood, then summarize or rank it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is a different shape from global ad-hoc analytics.&lt;/p&gt;
&lt;h2&gt;
  
  
  The practical design rule
&lt;/h2&gt;

&lt;p&gt;The practical rule is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not put unrelated data near each other unless the application expects to&lt;br&gt;
retrieve it together.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sounds obvious, but many systems lose this information after ingestion.&lt;br&gt;
The application knows that data belongs to a user, tenant, topic, source,&lt;br&gt;
document group, vector-search namespace, or RAG corpus segment. Then later,&lt;br&gt;
retrieval has to rediscover that relationship through indexes, joins, filters,&lt;br&gt;
ranking features, or model-based reranking.&lt;/p&gt;

&lt;p&gt;KoutenDB tries to keep that locality visible to the database.&lt;/p&gt;

&lt;p&gt;When writing data, the application or import rule chooses a ring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs/japan/search
users/123/context
web/github/nim/koutendb
products/42/reviews/2026
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When reading data, that same ring becomes the first retrieval scope for search,&lt;br&gt;
recommendation, RAG, vector retrieval, or application reads.&lt;/p&gt;

&lt;p&gt;That is the core idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  What KoutenDB is trying to prove
&lt;/h2&gt;

&lt;p&gt;The claim is not that every workload becomes faster automatically.&lt;/p&gt;

&lt;p&gt;The claim is narrower:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the storage layout captures useful data locality, then retrieval can avoid&lt;br&gt;
opening much of the unrelated dataset before ranking, vector search,&lt;br&gt;
reranking, or LLM context construction begins.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is why KoutenDB benchmarks focus on working-set reduction, scanned records,&lt;br&gt;
candidate memory, RAG token reduction, and tokens/query, not only raw key-value&lt;br&gt;
latency.&lt;/p&gt;

&lt;p&gt;In other words, KoutenDB is trying to make storage layout part of retrieval&lt;br&gt;
architecture. The target is not only faster reads, but less unnecessary work in&lt;br&gt;
candidate generation, pre-filtering, ranking, reranking, and context&lt;br&gt;
construction.&lt;/p&gt;

&lt;p&gt;Raw latency still matters. A locality-aware database cannot win if every local&lt;br&gt;
read is slow.&lt;/p&gt;

&lt;p&gt;But the larger bet is that reducing the amount of data touched can matter more&lt;br&gt;
than making a huge scan slightly faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this could matter at large scale
&lt;/h2&gt;

&lt;p&gt;At small scale, reading extra data is often tolerable.&lt;/p&gt;

&lt;p&gt;At search-engine, vector-search, or AI-platform scale, "extra data" becomes&lt;br&gt;
expensive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;more memory;&lt;/li&gt;
&lt;li&gt;more I/O;&lt;/li&gt;
&lt;li&gt;more I/O amplification;&lt;/li&gt;
&lt;li&gt;more network traffic;&lt;/li&gt;
&lt;li&gt;more ranking compute;&lt;/li&gt;
&lt;li&gt;more reranking compute;&lt;/li&gt;
&lt;li&gt;more LLM tokens;&lt;/li&gt;
&lt;li&gt;more cache churn;&lt;/li&gt;
&lt;li&gt;worse cache locality;&lt;/li&gt;
&lt;li&gt;wider tail latency;&lt;/li&gt;
&lt;li&gt;more infrastructure pressure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a system can avoid opening unrelated candidate regions in the first place,&lt;br&gt;
the benefit can be much larger than a small percentage optimization in one&lt;br&gt;
component.&lt;/p&gt;

&lt;p&gt;The useful mental model is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Data locality becomes the first-stage retrieval index.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ranking still matters. Search indexes still matter. Vector indexes still&lt;br&gt;
matter. Traditional database indexes still matter.&lt;/p&gt;

&lt;p&gt;But if the first stage can avoid reading most unrelated data, every later stage&lt;br&gt;
starts with a smaller problem.&lt;/p&gt;

&lt;p&gt;That is one of the main things KoutenDB is trying to explore.&lt;/p&gt;

&lt;p&gt;Project repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>search</category>
      <category>rag</category>
      <category>llm</category>
    </item>
    <item>
      <title>KoutenDB v0.6.0: Locality Validation, Topology Remapping, and Safer Query Boundaries</title>
      <dc:creator>puffball1567</dc:creator>
      <pubDate>Fri, 17 Jul 2026 17:27:11 +0000</pubDate>
      <link>https://dev.to/puffball1567/rochedb-v060-locality-validation-topology-remapping-and-safer-query-boundaries-2e1g</link>
      <guid>https://dev.to/puffball1567/rochedb-v060-locality-validation-topology-remapping-and-safer-query-boundaries-2e1g</guid>
      <description>&lt;p&gt;I released &lt;strong&gt;KoutenDB v0.6.0&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Release:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb/releases/tag/v0.6.0" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb/releases/tag/v0.6.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;KoutenDB is a ring-oriented NoSQL document and vector database written in Nim.&lt;br&gt;
The project is still a technical preview, but v0.6.0 is an important release&lt;br&gt;
because it moves more of the project from concept and happy-path demos toward&lt;br&gt;
measurable locality behavior.&lt;/p&gt;

&lt;p&gt;The main theme of this release is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If data locality is part of the database model, it should be tested as an&lt;br&gt;
invariant, not only described as an idea.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  What Changed
&lt;/h2&gt;

&lt;p&gt;v0.6.0 focuses on five areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;safer read filters;&lt;/li&gt;
&lt;li&gt;topology remapping foundations;&lt;/li&gt;
&lt;li&gt;locality validation workloads;&lt;/li&gt;
&lt;li&gt;easier operational configuration;&lt;/li&gt;
&lt;li&gt;practical use-case recipes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The release adds typed &lt;code&gt;KoutenFilterBuilder&lt;/code&gt; helpers so applications can build&lt;br&gt;
read filters without string-concatenating JSON.&lt;/p&gt;

&lt;p&gt;It also adds topology remapping primitives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;explicit arc tables;&lt;/li&gt;
&lt;li&gt;weighted arcs;&lt;/li&gt;
&lt;li&gt;deterministic virtual arcs;&lt;/li&gt;
&lt;li&gt;topology validation;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;remapFraction&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These do not mean KoutenDB has full online dynamic membership or live rebalance&lt;br&gt;
yet. They are lower-level primitives for modeling ownership and remapping&lt;br&gt;
behavior before exposing a larger operational protocol.&lt;/p&gt;
&lt;h2&gt;
  
  
  Locality As An Invariant
&lt;/h2&gt;

&lt;p&gt;The most interesting part of v0.6.0 is the locality validation work.&lt;/p&gt;

&lt;p&gt;KoutenDB's thesis is that meaningful placement can reduce unnecessary reads,&lt;br&gt;
transfers, memory pressure, and downstream AI/RAG work. But that claim needs to&lt;br&gt;
survive less friendly workloads than a clean first benchmark.&lt;/p&gt;

&lt;p&gt;So v0.6.0 adds workloads for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;random writes;&lt;/li&gt;
&lt;li&gt;delete-heavy patterns;&lt;/li&gt;
&lt;li&gt;backfill-heavy patterns;&lt;/li&gt;
&lt;li&gt;hot/cold data;&lt;/li&gt;
&lt;li&gt;interleaved writes;&lt;/li&gt;
&lt;li&gt;compaction before/after checks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The invariant is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The same logical ring query should return the same ID/payload set before and&lt;br&gt;
after compaction, while KoutenDB reports locality metrics such as candidate&lt;br&gt;
size and disk-span behavior.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That matters because data-locality systems can look good when data is inserted&lt;br&gt;
cleanly once. Real systems mutate, delete, backfill, and query from odd angles.&lt;br&gt;
This release starts testing that pressure directly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why This Matters For AI And RAG
&lt;/h2&gt;

&lt;p&gt;KoutenDB is not only for AI workloads, but AI/RAG is one of the clearest places&lt;br&gt;
where locality can matter.&lt;/p&gt;

&lt;p&gt;In many retrieval-heavy systems, the expensive part is not always finding one&lt;br&gt;
record. The expensive part is opening too much unrelated data, transferring it,&lt;br&gt;
holding it in memory, reranking it, summarizing it, or passing it downstream as&lt;br&gt;
LLM context.&lt;/p&gt;

&lt;p&gt;KoutenDB tries to make the application's natural locality part of the retrieval&lt;br&gt;
model.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs/japan/support
tenant/acme/orders/2026
users/123/profile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are not just labels after retrieval. In KoutenDB, rings are placement and&lt;br&gt;
read-scope units. A good ring can reduce the candidate set before more&lt;br&gt;
expensive ranking or application logic begins.&lt;/p&gt;

&lt;p&gt;v0.6.0 does not claim that KoutenDB is universally faster than Redis,&lt;br&gt;
PostgreSQL, MongoDB, Apache Arrow, or a dedicated vector database. The more&lt;br&gt;
careful claim is narrower:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;KoutenDB is building a database model where locality can be measured,&lt;br&gt;
preserved, and used to reduce unnecessary retrieval work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Safer Query Boundaries
&lt;/h2&gt;

&lt;p&gt;This release also adds typed filter helpers.&lt;/p&gt;

&lt;p&gt;Instead of building filter JSON by concatenating strings, applications can use&lt;br&gt;
structured helper APIs. That is not a flashy database feature, but it matters&lt;br&gt;
for a database that wants to be usable from application code and from multiple&lt;br&gt;
drivers.&lt;/p&gt;

&lt;p&gt;The same direction applies to the CLI and C ABI work in recent releases:&lt;br&gt;
KoutenDB is trying to keep the public surface small, explicit, and testable.&lt;/p&gt;
&lt;h2&gt;
  
  
  Operational Configuration
&lt;/h2&gt;

&lt;p&gt;v0.6.0 adds CLI connection config loading through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kouten &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kouten.json health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;KOUTEN_CONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kouten.json kouten health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"peers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1:17301"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"galaxy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"secret"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"secretKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shared-secret"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tlsCaFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"certs/ca.pem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tlsServerName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"koutendb.internal"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes local demos and small deployments easier to repeat without copying a&lt;br&gt;
long list of flags into every command.&lt;/p&gt;
&lt;h2&gt;
  
  
  Use-Case Recipes
&lt;/h2&gt;

&lt;p&gt;I also added &lt;code&gt;docs/use-case-recipes.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It covers examples such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;list/detail screens;&lt;/li&gt;
&lt;li&gt;membership records;&lt;/li&gt;
&lt;li&gt;inventory-style locks;&lt;/li&gt;
&lt;li&gt;webhook idempotency;&lt;/li&gt;
&lt;li&gt;SaaS tenant isolation;&lt;/li&gt;
&lt;li&gt;stellar neighborhood reads;&lt;/li&gt;
&lt;li&gt;RAG corpus layout.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point is to show where KoutenDB's model is useful outside benchmark scripts.&lt;br&gt;
KoutenDB is not trying to replace every database shape. It is trying to be strong&lt;br&gt;
when data has meaningful locality and when reducing the candidate working set&lt;br&gt;
matters.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try The Locality Demo
&lt;/h2&gt;

&lt;p&gt;The locality demo can be run with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;examples/locality_layout_demo.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It exercises different write patterns, compaction, and logical result checks.&lt;/p&gt;

&lt;p&gt;The important output is not just a speed number. It is whether KoutenDB can keep&lt;br&gt;
the logical query result stable while reporting how the physical layout changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current Boundaries
&lt;/h2&gt;

&lt;p&gt;KoutenDB remains a technical preview.&lt;/p&gt;

&lt;p&gt;Some important things are still not finished:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;online dynamic membership;&lt;/li&gt;
&lt;li&gt;live rebalance;&lt;/li&gt;
&lt;li&gt;cluster transaction coordinator redundancy;&lt;/li&gt;
&lt;li&gt;full production-grade operational hardening;&lt;/li&gt;
&lt;li&gt;larger real-corpus benchmarks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Universe sync remains an eventual-convergence primitive, not a consensus or&lt;br&gt;
quorum system.&lt;/p&gt;

&lt;p&gt;That boundary is intentional. I would rather keep the claims narrow and make&lt;br&gt;
the measurements stronger than present KoutenDB as a finished replacement for&lt;br&gt;
existing databases too early.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;Repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Release:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/puffball1567/koutendb/releases/tag/v0.6.0" rel="noopener noreferrer"&gt;https://github.com/puffball1567/koutendb/releases/tag/v0.6.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://puffball1567.github.io/koutendb/" rel="noopener noreferrer"&gt;https://puffball1567.github.io/koutendb/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next work after v0.6.0 is hardening: C ABI safety, TLS/C ABI build&lt;br&gt;
consistency, WAL integrity, data-directory locking, sync acknowledgement&lt;br&gt;
safety, and clearer release gates.&lt;/p&gt;

</description>
      <category>database</category>
      <category>ai</category>
      <category>rag</category>
      <category>nim</category>
    </item>
  </channel>
</rss>
