HeliosDB Nano is a SQL database, embedded in your process or run as a server, with native HNSW vector search, so embeddings and the rows they describe live in the same tables and are queried together with joins, SQL filters and transactions. Product Quantization is in the default build; durable restart-surviving PQ-HNSW indexes need the vector-persist build. Licensed Apache 2.0.
Last updated
Choose HeliosDB Nano when vectors sit next to relational data and you want joins, SQL filters and ACID transactions over both in one embedded or server database; keep a dedicated vector database when you need billions of vectors, a managed cloud service, built-in geographic distribution, or a vector-only workload.
Vector databases like Pinecone, Weaviate, Milvus, and Qdrant are purpose-built for vector search. HeliosDB Nano puts HNSW vector search inside a relational SQL engine, so one system can hold both the vectors and the data they describe.
| Feature | Pinecone | Weaviate | Qdrant | HeliosDB Nano |
|---|---|---|---|---|
| Vector Search | Yes | Yes | Yes | Yes |
| HNSW Index | Yes | Yes | Yes | Yes |
| Product Quantization | Yes | Yes | Yes | Yes (default build) |
| Full SQL | No | No | No | Yes |
| ACID Transactions | No | No | No | Yes |
| Joins | No | GraphQL | No | Yes |
| Aggregations | Limited | Limited | No | Full SQL |
| Deployment | Cloud-only | Self-host/Cloud | Self-host/Cloud | Embedded / Server |
| Offline Support | No | Manual | Manual | Yes |
| Metadata Filtering | Yes | Yes | Yes | SQL WHERE |
| Relational Data | No | No | No | Yes |
+---------------+ +---------------+ +---------------+
| Your App |---->| PostgreSQL | | Pinecone |
| |---->| (metadata) | | (vectors) |
+---------------+ +---------------+ +---------------+
| |
+--------------------+
Must sync manually
Problems:
+---------------+ +-------------------+
| Your App |---->| HeliosDB Nano |
| | | (vectors + SQL) |
+---------------+ +-------------------+
Benefits:
-- Same HNSW algorithm as Pinecone, Qdrant, etc.
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 200);
-- Tune search precision
SET hnsw.ef_search = 100;
-- Cosine distance (normalized vectors)
SELECT * FROM docs ORDER BY embedding <=> $query LIMIT 10;
-- Euclidean distance (L2)
SELECT * FROM docs ORDER BY embedding <-> $query LIMIT 10;
-- Inner product
SELECT * FROM docs ORDER BY embedding <#> $query LIMIT 10;
Product Quantization is in Nano's default build: add WITH (quantization='product') to an HNSW index. Indexes are unquantized unless you ask, and durable restart-surviving PQ-HNSW indexes need the vector-persist build, which keeps PQ codes in RAM with full vectors on disk and reranks results exactly (Product Quantization guide). Resident-memory savings and recall are measured on representative fixtures on the benchmarks page. Measure recall on your own embeddings before relying on any ratio.
-- Product Quantization in the default build
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (quantization = 'product');
-- HeliosDB Nano: One query for everything
SELECT
d.title,
d.content,
a.name AS author,
c.name AS category,
d.embedding <=> $query AS relevance
FROM documents d
JOIN authors a ON d.author_id = a.id
JOIN categories c ON d.category_id = c.id
WHERE c.name = 'Technology'
AND a.verified = true
ORDER BY relevance
LIMIT 10;
-- Vector DB: Requires multiple queries and app-side joins
-- HeliosDB Nano: Analytics on vector data
SELECT
category,
COUNT(*) AS doc_count,
AVG(embedding <=> $query) AS avg_relevance,
MIN(embedding <=> $query) AS best_match
FROM documents
WHERE embedding <=> $query < 0.5
GROUP BY category
ORDER BY avg_relevance;
-- Vector DB: Would need to export data for analysis
-- HeliosDB Nano: Atomic update of document and embedding
BEGIN;
UPDATE documents
SET content = $new_content, embedding = $new_embedding
WHERE id = $doc_id;
UPDATE search_index SET updated_at = NOW() WHERE doc_id = $doc_id;
COMMIT;
-- Vector DB: No transactional guarantees, eventual consistency
-- Complex filters that vector DBs struggle with
SELECT * FROM documents
WHERE embedding <=> $query < 0.5
AND created_at > NOW() - INTERVAL '30 days'
AND author_id IN (SELECT id FROM authors WHERE department = 'Engineering')
AND NOT EXISTS (
SELECT 1 FROM flagged_content
WHERE flagged_content.doc_id = documents.id
)
ORDER BY embedding <=> $query
LIMIT 10;
-- What were the search results a week ago? (needs retention that reaches back that far)
SELECT * FROM documents
AS OF TIMESTAMP '2026-01-19 00:00:00'
ORDER BY embedding <=> $query
LIMIT 10;
-- Compare embedding drift
SELECT
d.id,
d_old.embedding <=> d.embedding AS drift
FROM documents d
JOIN documents AS OF TIMESTAMP '2026-01-01' d_old ON d.id = d_old.id
WHERE d.embedding <=> d_old.embedding > 0.1;
# Export from Pinecone
import pinecone
index = pinecone.Index("my-index")
vectors = index.fetch(ids=all_ids)
# Import to HeliosDB Nano (embedded Python binding)
import json
import heliosdb_nano
db = heliosdb_nano.EmbeddedDatabase("./app-data")
db.execute("""
CREATE TABLE documents (
id TEXT PRIMARY KEY,
embedding VECTOR(768),
metadata JSONB
)
""")
db.execute_many(
"INSERT INTO documents (id, embedding, metadata) VALUES ($1, $2, $3)",
[(id, json.dumps(data['values']), json.dumps(data['metadata']))
for id, data in vectors.items()]
)
# Export from Qdrant
from qdrant_client import QdrantClient
client = QdrantClient("localhost", port=6333)
points = client.scroll("my_collection", limit=10000)[0]
# Import to HeliosDB Nano
db.execute_many(
"INSERT INTO documents (id, embedding, metadata) VALUES ($1, $2, $3)",
[(str(point.id), json.dumps(point.vector), json.dumps(point.payload))
for point in points]
)
We do not publish a head-to-head benchmark against Pinecone, Weaviate or Qdrant, so this page carries no throughput, latency or recall figures for them. Nano's own vector results, including Product Quantization memory and recall measured on representative fixtures, are on the benchmarks page, and all of them are single-node. Measure each candidate on your own data before choosing.
# Two separate systems
pg_conn = psycopg2.connect(PG_URL)
pinecone_index = pinecone.Index("docs")
def search(query):
# Get embedding
embedding = model.encode(query)
# Search vectors
vector_results = pinecone_index.query(embedding, top_k=10)
ids = [r.id for r in vector_results.matches]
# Fetch metadata from PostgreSQL
docs = pg_conn.execute(
"SELECT * FROM documents WHERE id = ANY($1)",
[ids]
)
# Manually combine results
return combine(vector_results, docs)
# One query does everything
def search(query):
embedding = model.encode(query)
return db.query("""
SELECT
d.*,
a.name AS author_name,
array_agg(t.name) AS tags,
d.embedding <=> $1::vector(768) AS relevance
FROM documents d
JOIN authors a ON d.author_id = a.id
LEFT JOIN document_tags dt ON d.id = dt.document_id
LEFT JOIN tags t ON dt.tag_id = t.id
WHERE d.embedding <=> $1::vector(768) < 0.5
GROUP BY d.id, a.name
ORDER BY relevance
LIMIT 10
""", [embedding])
Consider Pinecone, Qdrant, or similar if you:
::vector. That cast fails on a bound parameter today; inline literals work, and the Nano page shows a bound parameter with an explicit dimension ($1::vector(768)). Known limitationsCREATE INDEX on an expression is rejected. Known limitations| If you need... | Use... |
|---|---|
| Vector search + SQL | HeliosDB Nano |
| Vector search + relational joins | HeliosDB Nano |
| ACID transactions for vectors | HeliosDB Nano |
| Embedded/offline deployment | HeliosDB Nano |
| Billion-scale vectors | Dedicated vector DB |
| Managed cloud service | Dedicated vector DB |
| Vector-only workloads | Either works |
Get started with HeliosDB in minutes. Open source, free to use.