Experimental · Rust · no_std core

SQL, vectors and full-text search
in a single file

InlaySQL keeps SQLite's model — one file, no server, embed it anywhere — and adds concurrent writers, native vector and BM25 retrieval, and a MySQL wire protocol your ORM already speaks.

Still in development, and under heavy testing right now. The on-disk format is pre-1.0 (recreate, not migrate) and the MySQL server is plaintext and localhost-first — see What this is not below before you rely on it for anything real. If the idea here is one you'd use, tell us in Issues — what you'd need first is exactly what decides what gets built next.

1.36M point reads per second 1.33× SQLite in WAL mode
7.4× SQLite on concurrent writes 692 commits/s at 8 writers, 0% aborted
1 statement for hybrid search vector + BM25 fused in the engine
1145 SQL Logic Tests passing 100%, against SQLite's own corpus

Retrieval is not a bolt-on

A vector column and a full-text index live in the same file, in the same transaction, behind the same SQL. Fusing them is one statement — not two queries and a client-side merge.

-- A vector column is a column. An index is an index.
CREATE TABLE docs (
  id        INTEGER PRIMARY KEY,
  body      TEXT,
  embedding VECTOR(384)
);
CREATE INDEX docs_body      ON docs (body);       -- BM25
CREATE INDEX docs_embedding ON docs (embedding);  -- HNSW

-- Hybrid search, ranked by reciprocal rank fusion, in the engine.
SELECT id, body,
       fuse(vector_score(embedding, ?), bm25_score(body, ?)) AS score
FROM docs
ORDER BY score DESC
LIMIT 10;

What you get

Every claim here is backed by a test or a script in the repository.

One file, no server

Embed it in a binary, a CLI, or a browser tab. The same file opens natively, over WASM, and through the MySQL server — byte for byte.

Writers that do not queue

MVCC by structure: writers touching disjoint rows commit concurrently and are rebased rather than aborted. SQLite serialises at its file lock; we measured 0% aborts at every writer count.

Your ORM already speaks it

inlaysql serve --mysql talks the MySQL wire protocol. The statements a Laravel migration and Eloquent CRUD emit — including upsert(), eager loads and paginated reads — run over it, asserted end to end from Laravel 11's own grammars. Nobody has yet pointed a real php artisan migrate at it.

Crash safety you can replay

The core is no_std, so it cannot read a clock or touch a file except through a trait. That is what lets thousands of crash and torn-write schedules replay byte-for-byte on any machine.

Tested against SQLite itself

1145 SQL Logic Tests at 100%, plus a differential fuzzer that runs generated queries through both engines and compares the answers.

No unsafe code

inlaysql and inlaysql-core are #![forbid(unsafe_code)]. The one exception is the io_uring backend, isolated behind a trait.

Run it here

The engine below is compiled to WebAssembly and running in this tab — no server, no network round trip. It seeds a small corpus, indexes it for BM25 and vector search, and answers with the same code the native build runs.

loading the module…

    

The database is one file, in the same format the CLI reads. Saving hands those bytes to the origin-private file system; downloading gives you a file you can open with inlaysql serve --mcp.


    

Measured, including where we lose

Every number regenerates from a script in the repository. A table that contains only wins is advertising, so the losses are here too.

WorkloadInlaySQLCompared withResult
Point read by primary key 1,363,754 ops/s SQLite, WAL 1.33× faster
Concurrent writes, 8 writers 692 commits/s SQLite, journal 7.4× faster
Vector search, recall@10 1.000 70.8 µs sqlite-vec 9.5× faster
Hybrid search 0.875 ms DuckDB, pgvector ~14× faster
Durable write, one row per commit 723.1 ops/s PostgreSQL 17 beats it
Durable write, one row per commit 723.1 ops/s MySQL 8 1.08× slower
Join, 20k × 160k rows 54.1 ms SQLite 5.6× slower
Indexed range scan, 50 rows 14 µs SQLite, WAL 2.8× slower

One developer machine, one commit, one sitting. Reproduce it; do not trust it — ./bench/run.sh and ./bench/compare.sh are in the repository, and BENCHMARK.md records the machine, the durability settings and the asymmetries that remain.

What this is not, yet

Scheduled work rather than oversights — but you should know them before you reach for this.

Get started

# Not on crates.io yet — it is version 0.0.1 and the format is pre-1.0.
git clone https://github.com/inlaySQL/inlaysql
cd inlaysql

# Hybrid retrieval, end to end, in one example
cargo run --example hybrid_search

# Or serve a database over the MySQL wire protocol,
# then point your ORM at 127.0.0.1:3306
cargo run -p inlaysql-mcp --bin inlaysql -- serve --mysql app.inlay

Reading order for the repository: README for the pitch and the architecture, TESTING.md for what is covered and what is not, and the README's own Next section for what is being built and why.