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.
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;
Every claim here is backed by a test or a script in the repository.
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.
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.
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.
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.
1145 SQL Logic Tests at 100%, plus a differential fuzzer that runs generated queries through both engines and compares the answers.
inlaysql and inlaysql-core are
#![forbid(unsafe_code)]. The one exception is the
io_uring backend, isolated behind a trait.
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.
Every number regenerates from a script in the repository. A table that contains only wins is advertising, so the losses are here too.
| Workload | InlaySQL | Compared with | Result |
|---|---|---|---|
| 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.
Scheduled work rather than oversights — but you should know them before you reach for this.
# 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.