A lightweight vector search library for Rust.
memista pairs SQLite for metadata with USearch (HNSW) for similarity search, behind a three-endpoint Actix-web API. Embed the crate, or run the bundled binary as a standalone server. One process, two files on disk.
cargo add memista $ curl -X POST http://localhost:8083/v1/search \
-H "Content-Type: application/json" \
-d '{
"database_id": "my_app",
"query": [0.1, 0.2],
"limit": 5
}'
// → ranked chunk ids, text, metadata, distance
{
"results": [
{ "chunk_id": 42, "text": "Hello world", "distance": 0.03 }
]
} What is memista?
memista is a vector search library for Rust. It packages approximate nearest-neighbour search into a single crate: USearch for the index, SQLite for the chunk text and metadata, and Actix-web for a small HTTP layer. Embed it, or run the bundled binary. No separate database to operate.
USearch 2.19.x, HNSW graphs, SIMD via simsimd. Inner-product metric, F32.
SQLite table chunks_<id> holds text + metadata. Open it in sqlite3.
Three endpoints — insert, search, drop — on 127.0.0.1:8083.
One process. A .db and a .usearch file per partition. That's it.
The problems memista solves
Not every project that needs vector search needs a vector database.
A vector DB is too much machine
the problem
Your app needs retrieval over a few thousand chunks. Standing up a separate vector database — a container, a cluster, a thing to monitor and back up — is disproportionate.
memista's take
memista is a crate. It compiles into your binary, or runs as one small server. A partition is two files you can copy.
Bolting an index onto SQLite by hand
the problem
You already keep chunk text and metadata in SQLite. Adding ANN search means wiring an index crate, mapping row ids to vector keys, and keeping the two in sync yourself.
memista's take
memista does exactly that wiring: SQLite row id becomes the USearch key on insert, and search hydrates text back from SQLite. You call three endpoints.
Persistence you can't inspect
the problem
Opaque stores make debugging retrieval painful. When a result looks wrong, you want to open the data, not file a support ticket.
memista's take
Metadata is plain SQLite; the index is a <id>.usearch file. Inspect with sqlite3, back up with cp, reason about it on disk.
Retrieval that fights your language
the problem
A Rust agent, CLI, or desktop app shouldn't have to shell out to a Python service just to do similarity search.
memista's take
memista is Rust end to end (1.56+). Pull in create_app and AppState and mount the handlers inside your own Actix binary.
Insert over HTTP, or embed the crate
The same handlers, two ways to run them. Pick the shape that fits your app.
# Insert chunks: embedding + text + metadata
curl -X POST http://localhost:8083/v1/insert \
-H "Content-Type: application/json" \
-d '{
"database_id": "my_app",
"chunks": [{
"embedding": [0.1, 0.2],
"text": "Hello world",
"metadata": "{\"source\": \"readme\"}"
}]
}' // Mount memista's handlers in your own Actix binary
use memista::{AppState, Config, create_app};
use async_sqlite::{PoolBuilder, JournalMode};
use std::sync::Arc;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let config = Config::from_env().expect("config");
let db_pool = PoolBuilder::new()
.path(&config.database_path)
.journal_mode(JournalMode::Wal)
.open().await?;
let state = Arc::new(AppState { db_pool });
HttpServer::new(move || create_app(state.clone()))
.bind((config.server_host.as_str(), config.server_port))?
.run().await
}
Note: embedding dimensions are hardcoded to 2 in the stock crate — a demo default you edit in IndexOptions::dimensions before shipping.
How to change it →
Two well-known pieces, wired together
memista doesn't reinvent the index or the store — it makes them work as one small library.
Vector index
USearch HNSW under the hood, tuned for embeddable retrieval
USearch / HNSW index
Approximate nearest-neighbour search powered by USearch 2.19.x — HNSW graphs with SIMD acceleration via simsimd. The fast path for similarity queries.
Learn more →Inner-product metric
Distance is Inner Product (MetricKind::IP) with F32 quantization (ScalarKind::F32). Suited to normalised embeddings where cosine ranking is what you want.
Learn more →Metadata & persistence
SQLite you can open, back up, and reason about
SQLite metadata
Chunk text and metadata live in a plain SQLite table (chunks_<database_id>). Open it in sqlite3, inspect it, back it up with cp. No opaque store.
Learn more →Per-partition persistence
Each database_id gets its own SQLite table and its own <database_id>.usearch index file, using SQLite WAL. Isolation is by name; a partition is two files on disk.
Learn more →HTTP surface
Three endpoints and browsable OpenAPI docs via Actix-web
Actix-web HTTP API
A single binary starts an Actix-web server (default 127.0.0.1:8083) exposing three endpoints: POST /v1/insert, POST /v1/search, DELETE /v1/drop.
Learn more →OpenAPI docs built in
apistos generates an OpenAPI spec served through Swagger UI, Redoc, RapiDoc, and Scalar at /swagger, /redoc, /rapidoc, and /scalar. Explore the API in the browser.
Learn more →Shape & operations
A single binary that writes two files — nothing to orchestrate
Embed as a library
memista is a crate first. Pull in create_app and AppState and mount the same handlers inside your own Actix binary — or run the bundled server as-is.
Learn more →One process, two files
No Docker, no sidecar, no cluster. A partition is a .db and a .usearch file next to your app. The right shape for edge, desktop, and local-AI workloads.
Learn more →The whole API surface
Three endpoints on 127.0.0.1:8083. Plus browsable OpenAPI docs at
/swagger, /redoc, /rapidoc, /scalar.
/v1/insert Add chunks (embedding + text + metadata) to a partition. Returns the assigned chunk ids.
/v1/search k-nearest-neighbour query against a partition. Returns ranked chunks with text, metadata, and distance.
/v1/drop Drop a partition — its SQLite table and its .usearch index file.
Honest numbers only. memista is experimental (v0.1.x); we don't publish recall or latency benchmarks we haven't earned.
Explore memista
Everything on the site, one click from here.
Features
The USearch/HNSW index, inner-product metric, SQLite metadata, and the three-endpoint API — what memista actually ships.
Open →How it works
The architecture: an Actix-web HTTP layer over a SQLite store and a per-partition USearch index, kept in sync by chunk ids.
Open →API reference
POST /v1/insert, POST /v1/search, DELETE /v1/drop on 127.0.0.1:8083, plus browsable OpenAPI docs.
Open →Quickstart
Add the crate, start the server, insert a chunk, and run your first nearest-neighbour search in minutes.
Open →Guides
Step-by-step how-tos: install and run, insert over HTTP, search, change embedding dimensions, and handle persistence.
Open →Use cases
Where memista fits: embedded semantic search, RAG chunk stores, near-duplicate detection, recommendation, prototyping.
Open →Compare
How memista lines up against USearch direct, hnsw_rs, pgvector, and Qdrant — mostly a question of scope.
Open →Blog
Notes on embeddable vector search, ANN index trade-offs, and shipping retrieval inside a Rust binary.
Open →Glossary
Plain-language definitions of the vector search terms memista uses, from HNSW to quantization to recall.
Open →FAQ
Answers on the architecture, the inner-product metric, embedding dimensions, scale limits, and how to run it.
Open →About
Why Skelf Research built memista — because not every project that needs vector search needs a vector database.
Open →Ship retrieval in a Rust binary
memista is open source (GPL-3.0). Add the crate, run the server, insert some vectors, and query. No cluster to operate.
Part of Skelf Research
memista is one of a family of small, honest infrastructure tools.