v0.1.0 · early access · BSL 1.1

swindex is the small-world index for property graphs

Multi-hop graph queries in microseconds — a layered Leiden + hub-graph index in pure Rust, designed toward O(log N) traversal at billion-node scale. Sits beside your existing store; never replaces it.

Cargo
cargo add swindex --git https://github.com/k8nstantin/swindex
Clone & test
git clone git@github.com:k8nstantin/swindex.git cd swindex && cargo test
Embed in your app
use swindex::{Node, Edge, SliceSource}; let src = SliceSource::new(&nodes, &edges);

Concept

Indexes know where to look.
Databases hold what's there.

Vector indexes like HNSW transformed similarity search by exploiting the small-world structure that emerges from billion-vector corpora. Property graphs have the same emergent small-world structure — clusters, hubs, long-range bridges — but no equivalent index has shipped to production. So traversal-heavy workloads still scan edge-by-edge and degrade as graphs grow.

swindex is that index. Built from Leiden community detection, degree- and centrality-based hub selection, recursive aggregation, and Ada-IVF-style incremental maintenance. Every individual component is research-mature; the synthesis as a persistent, online, query-routing layer is what hadn't shipped.

Your data lives in whatever store already holds it — MySQL, Postgres, Iceberg, Parquet, an HTTP API. swindex stores only structural metadata: which cluster each node belongs to, which nodes are hubs, what the cluster graph looks like — and uses that metadata to narrow your queries by orders of magnitude before your primary store ever sees them.

On disk that's typically 2–5% the size of your underlying data. Your row payloads stay where they live.

What it does

Six built-in capabilities.

Each is research-mature in isolation. swindex's contribution is the synthesis as a persistent, online, query-routing index.

Leiden clustering

Mathematically guaranteed well-connected communities (Traag 2019). Parallel implementation; runs at O(N log N) over billion-edge graphs.

Hub detection

Identifies the 0.1–1% of nodes that are structurally pivotal. Built on the December 2024 "H in HNSW Stands for Hubs" insight applied to property data.

Recursive aggregation

Communities of communities of communities. Region graph routes queries before any per-node work happens, the same recursive pattern Microsoft GraphRAG uses offline.

Ada-IVF maintenance

Incremental, workload-aware re-clustering. ~5× higher sustained-write throughput than naive whole-index rebuilds. Only the clusters that drifted get re-Leidened.

Time-travel queries

Bitemporal cluster-assignment history. query_as_of(ts) resolves the cluster structure that existed at any past moment for audit and lineage.

Persistent storage

Fjall LSM for the hot working set (sub-ms lookups); Parquet on object storage for the cold history. Survives restarts; replicates cleanly.

How it works

Four layers. One query.

3

Region graph

Top-level Leiden communities of clusters. A few thousand nodes even at billion-fact scale. Routes a query to the right neighborhood before any real work happens.

2

Hub graph — the highway

A small fraction of nodes, selected by degree and betweenness centrality. The design's O(log N) navigation step; today's queries do a one-hop expansion through it.

1

Cluster graph

Leiden-detected, mathematically guaranteed well-connected communities of 100–10,000 nodes. Bounds the search space once hub navigation lands here.

0

Full fact graph

Ground truth. Persisted via Fjall (hot) plus Parquet (cold) for time-travel. Only touched inside the bounded set the upper layers have already narrowed to.

Architecture

swindex is a sidecar, not a store.

           application query
                  │
                  ▼
   ┌──────────────────────────┐
   │   swindex (Rust crate)   │
   │   ─────────────────────  │
   │   • cluster of node X?   │   ← microsecond cluster lookup
   │   • members of cluster?  │
   │   • nodes similar to X?  │
   │                          │   returns a small list of UUIDv7 ids
   └────────────┬─────────────┘
                │
   ┌────────────▼─────────────┐
   │  YOUR store (Iceberg /   │   ← columnar scan filtered by uuid7
   │  MySQL / Postgres / ...) │     returns the actual row payloads
   └──────────────────────────┘

In code

A minimal example.

src/main.rs
// Build a tiny property graph; show what swindex exposes today.
// (Index algorithms + query layers land in subsequent releases.)

use swindex::{Edge, EdgeKind, Node, NodeKind, SliceSource};

fn main() {
    let parcel = Node::fresh(NodeKind::new("parcel"));
    let owner  = Node::fresh(NodeKind::new("owner"));
    let owns   = Edge::fresh(owner.id, parcel.id, EdgeKind::new("owns"));

    let nodes = [parcel, owner];
    let edges = [owns];
    let _src = SliceSource::new(&nodes, &edges);

    println!("swindex {}", swindex::version());
}

License

Business Source License 1.1.

Free to embed in any product whose primary value is something other than swindex itself — applications, APIs, agents, pipelines, knowledge graphs. No friction. No royalty.

Hosted-index-as-a-service offerings require a commercial license. Standard BSL playbook.

Every release auto-converts to Apache 2.0 four years after it ships. Today's code becomes fully permissive over time; recent releases stay BSL until they age out.

Full text: LICENSE. Commercial inquiries: hello@swindex.ai.

Ready to get started?

Install swindex and start building. Read the design doc. Join the community.