Enterprise AI database · written in Rust

One database for enterprise AI

NebulaDB stores, indexes and retrieves your enterprise data with SQL, JSON documents, vectors, hybrid search and streaming RAG, and exposes all of it to AI agents over MCP. It is one Rust binary, built from the ground up for the workloads that relational and search databases were never designed to carry.

  • REST + SSE
  • gRPC
  • Postgres wire
  • MCP
  • Azure AI Search API
psql -h nebula -p 5433
-- vector retrieval and structured filters, one statement
SELECT id, title, region, severity
  FROM incidents
 WHERE semantic_match(content, 'TLS resets at checkout')
   AND region IN ('eu', 'uk')
   AND severity <= 2
 LIMIT 3;
idtitleregionseverity
pm-2310ECONNRESET in payment gatewayeu1
pm-2287p95 regression on checkout-apiuk2
pm-2251Handshake timeouts after cert rotationeu2
● 3 rows · HNSW top-k → residual filter · same engine over REST, gRPC and pgwire
~50klines of Rust
23workspace crates
500+unit + integration tests
4wire protocols, 1 binary
24MCP tools for agents
0GC pauses

Counted from the public repository: crates/**/*.rs and #[test] / #[tokio::test] attributes.

The problem

Traditional databases were not built for AI workloads

Enterprises bolt vector search onto relational databases, run a separate search cluster, and glue an embedder, a chunker and an LLM gateway on top. Each layer has its own deploy, its own auth and its own way to fail. NebulaDB takes those layers into the database.

  1. 01

    RAG is five services glued together

    Vector store, embedding service, chunking script, LLM gateway and a streaming layer: five processes, five deploys, five places for auth to leak.

    One binary does the pipeline. Ingest chunks and embeds server-side; POST /api/v1/ai/rag streams retrieved context and generated tokens over one SSE response, with citations.

    nebula-chunk · nebula-embed · nebula-llm · nebula-server
  2. 02

    Vectors are an extension, not a native type

    Bolted-on vector types share a planner, buffer pool and vacuum designed for rows. Similarity search competes with the workload the engine was tuned for.

    HNSW is the core index. Cosine, L2 and dot metrics, int8 quantisation with dequantisation fused into the distance loop, and SQL that plans semantic_match() as a first-class retrieval step.

    nebula-vector · nebula-sql
  3. 03

    Exact tokens get lost in embeddings

    Dense retrieval handles paraphrase but misses error codes, SKUs and function names. Teams run a second search engine to get them back.

    Hybrid search in the same index. Okapi BM25 and HNSW are fused with per-bucket weights, with optional query expansion and a pluggable reranker.

    nebula-bm25 · nebula-rerank · NEBULA_HYBRID_WEIGHTS
  4. 04

    In-memory vector indexes vanish on restart

    A pod restart drops the index and someone re-ingests from source, paying for every embedding again.

    Durable by design. Every mutation is CRC32-framed and fsynced to the WAL before it is applied. Boot loads the newest snapshot and replays the tail; a torn frame is truncated, never trusted. Vectors are stored in the log, so recovery needs no embedder.

    nebula-wal · nebula-index/durability · nebula-backup
  5. 05

    Analysts and agents cannot reach the vector store

    BI tools speak Postgres. Agents speak MCP. A bespoke REST dialect turns into adapters that nobody maintains.

    Every client speaks its own protocol. The same SQL engine serves REST, gRPC and the Postgres wire protocol, so psql works. A native MCP server gives agents 24 tools with auth passed through.

    nebula-pgwire · nebula-grpc · nebula-mcp · nebula-search
  6. 06

    HA and multi-region are bolted on later

    Replicas fall behind silently, compaction deletes segments a follower still needs, and a write to the wrong node diverges forever.

    Replication is part of the design. Raft within a region, home-region XDCR across regions, follower ack cursors that clamp WAL compaction, a write guard that returns 409 on followers, and a region-aware client that retries on the right home.

    nebula-raft · nebula-cdc · nebula-client · operator/

Why Rust from the ground up

The language is part of the database's guarantees

A database is judged on its worst millisecond and its worst crash. Rust lets NebulaDB keep the speed of C++ while ruling out whole classes of bugs at compile time.

  • 01

    No garbage-collector pauses

    Memory is freed deterministically by ownership. Tail latency for search and RAG is not hostage to a collector, which matters when an agent waits on every call.

  • 02

    Memory safety without a runtime

    Buffer overflows, use-after-free and data races are compile errors, not CVEs. The WAL and HNSW arena are written in safe Rust with checked UTF-8 chunk boundaries.

  • 03

    Concurrency the compiler checks

    Tokio serves REST, gRPC, pgwire and SSE from one async runtime. The HNSW graph uses per-node, per-layer locks, so readers search while writers insert.

  • 04

    Traits instead of glue

    Embedder, LlmClient, Chunker and Reranker are traits. Swap Ollama for OpenAI, Anthropic or Gemini by configuration; the deterministic mocks keep CI offline.

The workspace, crate by crate

Each concern is a separate crate with its own tests, so the boundaries in the diagram are the boundaries in the code.

  • AI and retrieval
  • Durability and HA
  • Protocols and clients
  • Core
  • nebula-coreIDs, error type and shared primitives
  • nebula-indexBuckets, chunks, parent/child docs, durable TextIndex
  • nebula-vectorHNSW graph, distance metrics, int8 quantisation
  • nebula-bm25Okapi BM25 inverted index for lexical recall
  • nebula-rerankReranker and query-expansion stages
  • nebula-embedEmbedder trait, OpenAI-compatible and Ollama clients
  • nebula-cacheIn-process LRU embedding cache
  • nebula-redis-cacheShared Redis tier, failure-transparent
  • nebula-chunkFixed, sentence, heading-aware and code-aware chunkers
  • nebula-llmStreaming LLM clients: Ollama, OpenAI, Anthropic, Gemini
  • nebula-sqlParser, typed plan tree, executor, result cache, EXPLAIN
  • nebula-walCRC-framed segments, subscribe API, ack-clamped compaction
  • nebula-raftRaft log, state machine and snapshots (openraft)
  • nebula-cdcTyped change events from the WAL to webhooks and files
  • nebula-backupSnapshot + WAL bundles to disk or S3, manifests, restore
  • nebula-resourceMemory, CPU and disk pressure → operating mode
  • nebula-serverAxum REST, SSE, auth, rate limit, audit, metrics
  • nebula-grpcTonic Document, Search and AI services
  • nebula-pgwirePostgres wire protocol over the same SQL engine
  • nebula-mcpModel Context Protocol server for agents
  • nebula-searchAzure AI Search-compatible API
  • nebula-clientRegion-aware SDK, retries to the home region
  • nebulactlBackup and restore CLI, run by the operator

See it work

The algorithms, running in your browser

These demos run the same algorithms NebulaDB uses, on toy data, so you can change a parameter and watch the effect. For the real thing over a live corpus, open the showcase.

Runs in your browser · 2-D toy vectors

Find neighbours without reading every vector

Click the graph to place a query. The search enters at the top layer, takes long hops through the sparse upper layers, then widens to a beam of ef candidates on layer 0. Green rings are the 5 results.

Distance calls–
Brute force–
Corpus touched–
Recall@5–
Layers–
Search ms–

Capabilities

Everything an AI application needs from its data layer

Store, index, understand, retrieve, answer and automate, on one highly available database.

  • SQL + JSON

    SQL over documents

    semantic_match() and vector_distance() beside filters, IN, array_contains, GROUP BY, inner joins and EXPLAIN. JSON metadata on every document.

    SQL and documents
  • Vectors

    HNSW and hybrid search

    Native HNSW with three metrics and int8 quantisation, BM25 fusion, query expansion, reranking and per-bucket weights.

    Vector and hybrid search
  • RAG

    Batteries-included RAG

    Smart chunking, embedding with a two-tier cache, grounded answers with [n] citations, history and caller-supplied context, streamed over SSE.

    RAG pipeline
  • Agents

    MCP for AI agents

    24 tools across SQL, search, RAG, documents, per-user long-term memory, cluster health, replication, backups and audit. Every tool declares whether it writes.

    Agents and MCP
  • HA

    Replicated, multi-region

    Raft within a region, home-region XDCR across regions, follower promotion, zero-downtime swap rebalance and a Kubernetes operator.

    High availability
  • Operations

    Durable and observable

    WAL, snapshots, backup to S3 and restore, CDC, Prometheus metrics with Grafana dashboards, live log streaming, slow-query log, audit log and graceful degradation.

    Durability and operations

Architecture

One engine behind every protocol

Every surface calls the same index, so a bug fix or a feature lands everywhere at once and REST, gRPC, pgwire and MCP can never disagree.

NebulaDB architecture Clients and agents connect over REST, gRPC, Postgres wire and MCP to nebula-server. The server routes to the SQL planner and the retrieval pipeline, which share one durable index of HNSW vectors, BM25 and documents. The index writes to a WAL that feeds snapshots, Raft followers, cross-region XDCR, CDC and backups. CLIENTS Apps · curlREST + SSE ServicesgRPC (tonic) BI · psql · ORMsPostgres wire AI agentsMCP · nebula-mcp Azure AI Searchcompat API nebula-server rate limit → audit → follower write guard → API key / JWT → handler · /healthz and /metrics bypass auth SQL planner · nebula-sql parse → typed plan → semantic_match → filters GROUP BY · JOIN · result cache · EXPLAIN Retrieval and RAG chunk → embed (LRU → Redis) → expand → hybrid → rerank → prompt → LLM stream (Ollama · OpenAI · Anthropic · Gemini) Durable index · nebula-index HNSW vectors BM25 postings documents + metadata WAL · nebula-wal → snapshots · backup to S3 · restore → Raft followers · XDCR to regions → CDC events · webhooks

Read the architecture

Compared with a typical stack

What changes when the database understands AI

ConcernRelational DB + extensions + glueNebulaDB
Vector searchExtension type on a row engine; tuning shared with OLTPNative HNSW, int8 quantisation, planned by SQL
Keyword recallSeparate search cluster to operate and syncBM25 in the same index, fused per bucket
RAG pipelineChunker, embedder, LLM gateway and streamer as separate servicesServer-side chunk, embed, retrieve and stream over one SSE call
Embedding costCache built per application, if at allLRU + Redis tiers with hit/miss metrics
AI agentsCustom tool wrappers per frameworkMCP server with 24 typed tools, auth passed through
RestartIn-memory vector indexes rebuilt from sourceSnapshot + WAL replay, no re-embedding
Multi-regionReplicate each component separatelyHome-region XDCR for documents and vectors together
RuntimeMixed: C, JVM, Python, NodeOne Rust binary, no GC

Quick start

Running in one command

The start script picks free ports, builds the stack, pulls local models through Ollama, seeds a corpus and prints the URLs. No external AI API is required.

terminal
git clone https://github.com/bwalia/nebuladb
cd nebuladb
./scripts/start.sh                 # tinyllama + nomic-embed-text
./scripts/start.sh --model llama3  # a larger chat model
docker / helm
docker pull bwalia/nebula-server:latest
docker pull bwalia/nebula-showcase:latest

helm install nebula deploy/helm/nebuladb
  1. Ingest

    POST /api/v1/bucket/docs/document chunks and embeds server-side.

  2. Search

    POST /api/v1/ai/search, vector or hybrid.

  3. Answer

    POST /api/v1/ai/rag streams context then tokens.

  4. Query

    psql -p 5433 with semantic_match().

Honest limits

What NebulaDB does not do yet

Knowing where a system stops is part of choosing it. These are documented in the repository and return clear errors rather than surprising results.

  • SQL subsetNo OR in WHERE, outer joins, subqueries, CTEs or HAVING. Unsupported syntax returns 400 sql_unsupported (SQLSTATE 42601 on pgwire).
  • Simple query protocol onlypsql works; drivers that require the extended protocol (prepare / bind) do not yet.
  • One writer per bucketMulti-region is active-active per cluster, with each bucket homed in one region. No multi-master writes to the same bucket.
  • No cross-document transactionsEach upsert is its own durable commit.
  • Coarse access controlAPI keys and JWT grant API access; there are no row- or field-level ACLs inside search results.
  • Index in RAMThe working index lives in memory with snapshots on disk; there is no cold-storage tiering for rarely used vectors.

Showcase

See it on a live corpus

The showcase runs NebulaDB over real data: Companies House due diligence, a shop catalogue, Talent Match, Incident Copilot, Contract Review and Support Desk, plus cluster, rebalance and backup views.