Skip to content

Repository files navigation

SQLite AI

SQLite-Vector

Production-grade vector search inside SQLite.
Exact search, SIMD distance kernels, and SIMD 2/3/4-bit TurboQuant scans — runs anywhere SQLite runs: mobile, browser, edge, server.

Free managed instance → · Docs · Website · Blog

Data: Vector · Sync · Columnar · JS
AI: AI · Agent · Memory · MCP


Building RAG or semantic search? SQLite-Vector ships as an extension you can drop into any SQLite app. Need it managed with sync and auth? SQLite Cloud free tier gives you 512 MB and 20 connections, no credit card.


SQLite Vector

SQLite Vector is a cross-platform, ultra-efficient SQLite extension that brings vector search capabilities to your embedded database. It works seamlessly on iOS, Android, Windows, Linux, and macOS, using just 30MB of memory by default. With support for Float32, Float16, BFloat16, Int8, UInt8, 1Bit, and TurboQuant 2/3/4-bit quantization, plus highly optimized distance functions, it's the ideal solution for Edge AI applications.

SQLite-Vector includes TurboQuant, a compact data-oblivious vector quantizer inspired by the Google Research paper TurboQuant: Online Vector Quantization with Near-Optimal Distortion Rate. It stores each vector as low-bit scalar codes plus one scale value, then scores directly from SIMD lookup-table kernels without reconstructing full vectors.

Highlights

  • No virtual tables required – store vectors directly as BLOBs in ordinary tables
  • Blazing fast – optimized C implementation with SIMD acceleration
  • TurboQuant support – SIMD 2-, 3-, and 4-bit quantization scans with qtype=TURBO
  • Low memory footprint – defaults to just 30MB of RAM usage
  • Zero preindexing needed – no long preprocessing or index-building phases
  • Works offline – perfect for on-device, privacy-preserving AI workloads
  • Plug-and-play – drop into existing SQLite workflows with minimal effort
  • Cross-platform – works out of the box on all major OSes

Why Use SQLite-Vector?

Feature SQLite-Vector Traditional Solutions
Works with ordinary tables ❌ (usually require special virtual tables)
Doesn't need preindexing ❌ (can take hours for large datasets)
Doesn't need external server ❌ (often needs Redis/FAISS/Weaviate/etc.)
Memory-efficient
TurboQuant low-bit scanning
Easy to use SQL ❌ (often complex JOINs, subqueries)
Offline/Edge ready
Cross-platform

Unlike other vector databases or extensions that require complex setup, SQLite-Vector just works with your existing database schema and tools.

Installation

Pre-built Binaries

Download the appropriate pre-built binary for your platform from the official Releases page:

  • Linux: x86 and ARM
  • macOS: x86 and ARM
  • Windows: x86
  • Android
  • iOS

Loading the Extension

-- In SQLite CLI
.load ./vector

-- In SQL
SELECT load_extension('./vector');

Or embed it directly into your application.

WASM Version

You can download the WebAssembly (WASM) version of SQLite with the SQLite Vector extension enabled from: https://www.npmjs.com/package/@sqliteai/sqlite-wasm

Example Usage

-- Create a regular SQLite table
CREATE TABLE images (
  id INTEGER PRIMARY KEY,
  embedding BLOB, -- store Float32/UInt8/etc.
  label TEXT
);

-- Insert a BLOB vector (Float32, 384 dimensions) using bindings
INSERT INTO images (embedding, label) VALUES (?, 'cat');

-- Insert a JSON vector (Float32, 384 dimensions)
INSERT INTO images (embedding, label) VALUES (vector_as_f32('[0.3, 1.0, 0.9, 3.2, 1.4,...]'), 'dog');

-- Initialize the vector. By default, the distance function is L2.
-- To use a different metric, specify one of the following options:
-- distance=L1, distance=COSINE, distance=DOT, distance=SQUARED_L2, or distance=HAMMING.
SELECT vector_init('images', 'embedding', 'type=FLOAT32,dimension=384');

-- If your embeddings are already unit length, say so: FLOAT32 cosine scans then compute
-- 1 - dot instead of the full cosine, with the same results.
-- SELECT vector_init('images', 'embedding', 'type=FLOAT32,dimension=384,distance=COSINE,normalized=1');

-- Quantize vector
SELECT vector_quantize('images', 'embedding');

-- Or use TurboQuant for compact 2/3/4-bit quantization
SELECT vector_quantize('images', 'embedding', 'qtype=TURBO,qbits=4');

-- Optional preload quantized version in memory (for a 4x/5x speedup) 
SELECT vector_quantize_preload('images', 'embedding');

-- Run a nearest neighbor query on the quantized version (returns top 20 closest vectors)
SELECT e.id, v.distance FROM images AS e
   JOIN vector_quantize_scan('images', 'embedding', ?, 20) AS v
   ON e.id = v.rowid;

-- Streaming mode: omit k to get rows progressively, use SQL to filter and limit
SELECT e.id, v.distance FROM images AS e
   JOIN vector_quantize_scan('images', 'embedding', ?) AS v
   ON e.id = v.rowid
   WHERE e.label = 'cat'
   LIMIT 10;

Benchmark

Every number below comes from one command, so you can reproduce it and compare machines:

make benchmark

That builds test/benchmark.c at -O3 with the same per-translation-unit SIMD flags the shipped extension uses, then searches k=20 over 1,000,000 vectors of dimension 768 with cosine distance, 20 queries, reporting the best. Recall is the overlap with the exact full-precision top-20. Override any of it:

make benchmark NVECS=100000 DIM=384 K=10 DISTANCE=l2

Apple M5 Pro (6P+12E, 64 GB, macOS 26.6.2) — NEON backend

Mode Index ms/query Mvec/s Recall@20
FLOAT32 exact 2930 MB 147.8 6.8 100.0%
UINT8 740 MB 55.4 18.0 33.8%
UINT8 preloaded 740 MB 37.2 26.9 33.8%
INT8 740 MB 56.4 17.7 99.5%
INT8 preloaded 740 MB 37.7 26.5 99.5%
1BIT 99 MB 5.3 187.5 10.0%
1BIT preloaded 99 MB 2.7 377.6 10.0%
TURBO2 195 MB 53.0 18.9 45.2%
TURBO2 preloaded 195 MB 48.2 20.7 45.2%
TURBO4 378 MB 160.4 6.2 81.8%
TURBO4 preloaded 378 MB 151.8 6.6 81.8%

Contributions from other CPUs welcome — run the command above and open a PR adding a section.

Reading the table

The data is uniform random, which is the worst case for every quantizer: real embeddings have structure that quantization exploits, so recall on your own vectors will be higher, often much higher. Treat the recall column as a floor and a way to rank the modes against each other, not as a prediction for your dataset.

Three things are worth knowing before you pick a mode.

For cosine, use INT8, not UINT8. They cost exactly the same and store exactly the same number of bytes, but UINT8 recall collapses to 33.8% while INT8 holds 99.5%. Unsigned quantization subtracts the dataset minimum before scaling, and cosine measures angle, which that shift destroys. UINT8 is the right choice for L2, where a common translation cancels out. If you do not set qtype, the extension picks UINT8 for non-negative data and INT8 otherwise — which is the correct call for L2 and the wrong one for cosine, so set it explicitly when you use cosine.

1BIT is a filter, not an answer. 377 Mvec/s and 30x less memory, at 10% recall on this data. It earns its place as a first pass whose survivors you re-rank at full precision, not as the final ranking.

TurboQuant trades speed for size, not for speed. TURBO4 here is slower than the exact scan (160 ms against 148 ms) while using 8x less memory and returning 81.8% recall. The lookup-table scan is one table gather per row, and at dimension 768 that is 384 gathers into a 393 KB table for every vector — already about one lookup per cycle, so there is no headroom left in the current storage layout. Choose TurboQuant when the memory budget is what binds; choose INT8 when throughput is.

TurboQuant Benchmark and Recall

TurboQuant can be selected with qtype=TURBO,qbits=N, where N is 2, 3, or 4. Shorthand aliases are also available: TURBO2, TURBO3, and TURBO4.

-- Highest recall TurboQuant mode currently recommended as the default
SELECT vector_quantize('images', 'embedding', 'qtype=TURBO,qbits=4');

-- Smaller edge-oriented representation
SELECT vector_quantize('images', 'embedding', 'qtype=TURBO2');

An earlier synthetic benchmark reported speedups of 15x for 4-bit and 38x for 2-bit against vector_full_scan(). Those numbers were measured with a file-backed database, where the full scan reads 3 GB of raw vectors off disk and the comparison is dominated by I/O rather than by arithmetic — and before the distance kernels were rewritten, which made the full-precision scan itself substantially faster. Against an in-memory baseline on current code the picture is different: see Benchmark below, where TURBO4 is marginally slower than the exact scan and its argument is memory, not speed. Both measurements are real; they answer different questions. If your working set does not fit in RAM, the file-backed comparison is the one that describes your deployment.

For comparison, the raw FLOAT32 vectors alone are about 3.07 GB for 1M x 768 before SQLite row/page overhead. TurboQuant 4-bit reduces the scan representation to about 13% of that raw vector payload, TurboQuant 3-bit to about 10%, and TurboQuant 2-bit to about 7%. Actual resident memory depends on whether the database is in-memory or file-backed, SQLite cache settings, preloading, page cache behavior, and the host allocator.

The TurboQuant scan backend can be checked separately from the regular distance backend:

SELECT vector_backend(), vector_turboquant_backend();

For edge deployments, vector_quantize_memory(table, column) estimates the quantized scan representation. TurboQuant stores each row as rowid + scale + packed_codes, roughly rows * (8 + 4 + ceil(dim * qbits / 8)) bytes before allocator and SQLite cache overhead. The synthetic benchmark in test/benchmark_turboquant.c also supports PRELOAD=0 to compare the lower-RAM, non-preloaded path.

Real-dataset recall can be reproduced with test/recall_turboquant_real.py, which downloads Fashion-MNIST in the ANN-Benchmarks HDF5 format and compares TurboQuant against vector_full_scan() using L2 distance. Example run on macOS ARM64/NEON with 10,000 base vectors, 50 queries, and k=10:

Mode Quantized storage Full scan / query TurboQuant / query Speedup Recall@10
TurboQuant 4-bit 4.04 MB 16.32 ms 4.80 ms 3.40x 0.948
TurboQuant 3-bit 3.06 MB 16.32 ms 8.28 ms 1.97x 0.868
TurboQuant 2-bit 2.08 MB 16.32 ms 1.86 ms 8.78x 0.596

qbits=4 is the recommended starting point when recall matters. qbits=2 is useful for tighter edge memory budgets, but should be validated on the target embeddings because recall can drop significantly depending on the dataset.

Swift Package

You can add this repository as a package dependency to your Swift project. After adding the package, you'll need to set up SQLite with extension loading by following steps 4 and 5 of this guide.

Here's an example of how to use the package:

import vector

...

var db: OpaquePointer?
sqlite3_open(":memory:", &db)
sqlite3_enable_load_extension(db, 1)
var errMsg: UnsafeMutablePointer<Int8>? = nil
sqlite3_load_extension(db, vector.path, nil, &errMsg)
var stmt: OpaquePointer?
sqlite3_prepare_v2(db, "SELECT vector_version()", -1, &stmt, nil)
defer { sqlite3_finalize(stmt) }
sqlite3_step(stmt)
log("vector_version(): \(String(cString: sqlite3_column_text(stmt, 0)))")
sqlite3_close(db)

Android Package

Add the following to your Gradle dependencies:

implementation 'ai.sqlite:vector:0.9.80'

Here's an example of how to use the package:

SQLiteCustomExtension vectorExtension = new SQLiteCustomExtension(getApplicationInfo().nativeLibraryDir + "/vector", null);
SQLiteDatabaseConfiguration config = new SQLiteDatabaseConfiguration(
    getCacheDir().getPath() + "/vector_test.db",
    SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.OPEN_READWRITE,
    Collections.emptyList(),
    Collections.emptyList(),
    Collections.singletonList(vectorExtension)
);
SQLiteDatabase db = SQLiteDatabase.openDatabase(config, null, null);

Note: Additional settings and configuration are required for a complete setup. For full implementation details, see the complete Android example.

Python Package

Python developers can quickly get started using the ready-to-use sqlite-vector package available on PyPI:

pip install sqliteai-vector

For usage details and examples, see the Python package documentation.

Flutter Package

Add the sqlite_vector package to your project:

flutter pub add sqlite_vector  # Flutter projects
dart pub add sqlite_vector     # Dart projects

Usage with sqlite3 package:

import 'package:sqlite3/sqlite3.dart';
import 'package:sqlite_vector/sqlite_vector.dart';

sqlite3.loadSqliteVectorExtension();
final db = sqlite3.openInMemory();
print(db.select('SELECT vector_version()'));

For a complete example, see the Flutter example.

Documentation

Extensive API documentation can be found in the API page.

More information about the quantization process can be found in the QUANTIZATION document.

Features

Instant Vector Search – No Preindexing Required

Unlike other SQLite vector extensions that rely on complex indexing algorithms such as DiskANN, HNSW, or IVF, which often require preprocessing steps that can take hours or even days, sqlite-vector works out of the box with your existing data. There’s no need to preindex your vectors—you can start performing fast, approximate or exact vector searches immediately.

This means:

  • No waiting time before your app or service is usable
  • Zero-cost updates – you can add, remove, or modify vectors on the fly without rebuilding any index
  • Works directly with BLOB columns in ordinary SQLite tables – no special schema or virtual table required
  • Ideal for edge and mobile use cases, where preprocessing large datasets is not practical or possible

By eliminating the need for heavyweight indexing, sqlite-vector offers a simpler, faster, and more developer-friendly approach to embedding vector search in your applications.

Supported Vector Types

You can store your vectors as BLOB columns in ordinary tables. Supported formats include:

  • float32 (4 bytes per element)
  • float16 (2 bytes per element)
  • bfloat16 (2 bytes per element)
  • int8 (1 byte per element)
  • uint8 (1 byte per element)
  • 1bit (1 bit per element)

Simply insert a vector as a binary blob into your table. No special table types or schemas are required.

A stored column is quantized separately with vector_quantize(table, column, 'qtype=...'), which builds a compact index the scan reads instead of the raw vectors:

qtype Bytes per dimension Notes
UINT8 1 Asymmetric. Correct for L2; see the benchmark before using it with cosine
INT8 1 Symmetric. The default choice for cosine
1BIT 1/8 Hamming only. A pre-filter to re-rank, not a final ranking
TURBO2 / TURBO3 / TURBO4 1/4, 3/8, 1/2 Lookup-table scan; smallest indexes, see TurboQuant

Omitting qtype picks UINT8 for non-negative data and INT8 otherwise. BIT columns are already binary, so 1BIT is the only quantization they accept.

Supported Distance Metrics

Optimized implementations available:

  • L2 Distance (Euclidean)
  • Squared L2
  • L1 Distance (Manhattan)
  • Cosine Distance
  • Dot Product
  • Hamming Distance (available only with 1bit vectors — vector_init() rejects it for any other type)

These are implemented in pure C and optimized for SIMD when available, ensuring maximum performance on modern CPUs and mobile devices.

If your embeddings are already unit length, say so with normalized=1: cosine on a FLOAT32 column then reduces to 1 - dot, dropping two thirds of the arithmetic from the inner loop for the same results. It is an assertion about your data, not a request — see API.md.


What Is Vector Search?

Vector search is the process of finding the closest match(es) to a given vector (a point in high-dimensional space) based on a similarity or distance metric. It is essential for AI and machine learning applications where data is often encoded into vector embeddings.

Common Use Cases

  • Semantic Search: find documents, emails, or messages similar to a query
  • Image Retrieval: search for visually similar images
  • Recommendation Systems: match users with products, videos, or music
  • Voice and Audio Search: match voice queries or environmental sounds
  • Anomaly Detection: find outliers in real-time sensor data
  • Robotics: localize spatial features or behaviors using embedded observations

In the AI era, embeddings are everywhere – from language models like GPT to vision transformers. Storing and searching them efficiently is the foundation of intelligent applications.

Perfect for Edge AI

SQLite-Vector is designed with the Edge AI use case in mind:

  • Runs offline – no internet required
  • Works on mobile devices – iOS/Android friendly
  • Keeps data local – ideal for privacy-focused apps
  • Extremely fast – real-time performance on device

You can deploy powerful similarity search capabilities right inside your app or embedded system – no cloud needed.


License

Free Use in Open-Source Projects: You may use, copy, distribute, and prepare derivative works of the software — in source or object form, with or without modification — freely and without fee, provided the software is incorporated into or used by an open-source project licensed under an OSI-approved open-source license. Everything else is licensed under the Elastic License 2.0. You can use, copy, modify, and distribute it under the terms of the license for non-production use. For production or managed service use, please contact SQLite Cloud, Inc for a commercial license.


☁️ Hosted version

Don't want to run it yourself? SQLite Cloud is the managed version of SQLite-Vector and the rest of the stack — with sync, backups, auth, edge functions, and multi-region support included.

Start free →


Part of the SQLite AI stack

SQLite-Vector is one piece of a larger ecosystem that turns SQLite into a runtime for intelligent, distributed data:

Data layer

  • sqlite-vector — ANN vector search inside SQLite (you are here)
  • sqlite-sync — Offline-first CRDT sync across devices
  • sqlite-columnar — Column-oriented analytics for OLAP queries
  • sqlite-js — Custom SQLite functions written in JavaScript

AI layer

  • sqlite-ai — On-device LLM inference and embeddings
  • sqlite-agent — Autonomous AI agents running inside SQLite
  • sqlite-memory — Persistent, searchable memory for agents
  • sqlite-mcp — Call MCP tools directly from SQL queries

Managed platform

Built by SQLite AI. Questions? Contact us.

About

SQLite-Vector is a cross-platform, ultra-efficient SQLite extension that brings vector search capabilities to your embedded database.

Resources

Stars

1.1k stars

Watchers

13 watching

Forks

Releases

Packages

Contributors

Languages