SQLite Grew Up: Meet Elyra SQL Anywhere
Every developer has a soft spot for SQLite. It's the database that just works — one file, no server, no config, no 3 a.m. pages about a connection pool. It's in your phone, your browser, your tests, probably your toaster. But there's always been a moment, usually around the time your app finds its second user, when you sigh and say: "Well, time to move to Postgres." What if you didn't have to?
Usually around the time your app finds its second user, when you sigh and say: "Well, time to move to Postgres." What if you didn't have to?
That's the quiet promise of Elyra SQL Anywhere.
The pitch, in one breath
SQL Anywhere is a fork of SQLite that keeps everything you love — the file format, the C API, the zero-ceremony simplicity — and adds the handful of things that used to force you to graduate to a "real" database. Replication. A server mode. Continuous backup to the cloud. Encryption. And, as of recently, native vector search.
It's not a rewrite. It's not SQLite-inspired. It's SQLite, with the ceiling raised. Databases that don't touch the new features stay byte-compatible with stock SQLite tooling — your existing .db files, your sqlite3 CLI, your favourite GUI all keep working.
From one file to everywhere
The magic is that the same engine scales across three very different shapes, and you pick the one you need without changing databases:
Embedded. Link the sqlanywhere Rust crate and you've got an in-process database, exactly like classic SQLite. Sub-millisecond reads, no network, no fuss.
let db = Builder::new_local(":memory:").build().await?;
let conn = db.connect()?;
conn.execute("CREATE TABLE users (email TEXT)", ()).await?;
Embedded replica. Point that same API at a remote primary and suddenly you've got a live, local copy that syncs in the background. Your reads are served from disk in microseconds; your writes propagate upstream. This is the trick that makes "edge" feel less like a buzzword and more like a Tuesday.
let db = Builder::new_local_replica("local.db").build().await?;
db.sync().await?; // pull the latest frames
let conn = db.connect()?; // reads stay local
Server. Run sqld and your database speaks HTTP and WebSockets, so remote clients connect like they would to Postgres or MySQL — complete with namespaces and an admin API. One binary, many databases.
Same data, same SQL, same file format. You move along the spectrum as your needs grow, instead of migrating to a different system and rewriting half your data layer.
The grown-up features, without the grown-up weight
Here's what got added on top of the SQLite you know:
Replication — ship the write-ahead log from a primary to replicas with frame injection. Read replicas and embedded replicas are built from the same primitives.
Bottomless storage — stream the WAL continuously to S3-compatible object storage. Your database becomes durable and point-in-time recoverable, and "bottomless" because the local disk is just a cache of an infinite remote.
Encryption — at rest and in transit, built in.
Offline writes — accept writes while disconnected, reconcile when you're back. Perfect for mobile and the edge.
Multitenancy & namespaces — serve many independent databases from one
sqldinstance, with path-based routing.A pluggable virtual WAL — swap in custom write-ahead-log backends if you're doing something exotic.
Bindings everywhere — an async Rust API, plus C and WebAssembly, so the same engine runs from native apps all the way into the browser.
None of this asks you to give up the thing that made SQLite great. It's still just a file, until you decide it shouldn't be.
The new headline act: vectors
Here's the part that makes 2026 feel like 2026. SQL Anywhere has native vector search — embeddings are a first-class column type, not a bolted-on extension and not a separate vector database you have to operate alongside your real one.
CREATE TABLE movies (
title TEXT,
embedding F32_BLOB(4)
);
INSERT INTO movies VALUES
('Inception', vector32('[0.1,0.2,0.3,0.4]'));
-- Build an approximate-nearest-neighbour index
CREATE INDEX movies_idx ON movies (libsql_vector_idx(embedding));
-- Find the nearest neighbours
SELECT title FROM vector_top_k('movies_idx', vector32('[0.2,0.1,0.4,0.3]'), 5)
JOIN movies ON movies.rowid = id;
That's it. No Pinecone, no pgvector setup, no second datastore to keep in sync. Store your embeddings next to your data, build a DiskANN index, and run similarity search with plain SQL — and because it's the same engine, that vector search works embedded, replicated, and on the server. The RAG app you were going to build with three moving parts might only need one.
Why it's lovely
The best technology often isn't the most novel — it's the kind that removes a decision you didn't want to make. SQL Anywhere removes the "ugh, time to leave SQLite" decision. You start with a file. If you need a replica, you get a replica. If you need a server, you flip to a server. If you need vector search, it's already there. The engine grows with the app instead of being something you grow out of.
It's Rust-built, MIT-licensed, fully open, and stays a drop-in SQLite the whole way up. Currently at v0.2.0 — the first stabilization release after the fork, with prebuilt sqld binaries for macOS and Linux ready to download.
Try it
Browse the docs: elyracode.com/docs/sql-anywhere — start with the installation guide.
Grab a binary or read the highlights: elyracode.com/sql-anywhere
Embed it in Rust:
cargo add sqlanywhere
SQLite never needed fixing. It just needed room to grow. SQL Anywhere gives it that room — and throws in vectors while it's at it.