semantic

Vectors

Auto-embed on insert, similarity search, no vector DB to sync.

What it is

Vectors on RedDB.

Vector indexes natively, with a write path that handles embedding on the way in. INSERT … WITH AUTO EMBED USING <provider> resolves text to a vector at ingest, against any OpenAI-compatible API.

Similarity search runs as SEARCH SIMILAR against the same wire protocol the rest of your app already uses. Metadata filters, hybrid full-text + vector queries, and IVF / HNSW indexing land in standard SQL surface.

Pairs with graphsSEARCH SIMILAR … WITH CONTEXT DEPTH 2 returns nearest neighbours plus their relational neighbourhood for RAG.

Code

Write it. Read it. Same engine.

Insert

INSERT INTO notes (body) VALUES ('suspicious vpn login from new country') WITH AUTO EMBED (body) USING openai;

Query

SEARCH SIMILAR TEXT 'login anomaly' COLLECTION notes LIMIT 10;

Driver examples

Connect from your language.

Real driver code — copy-paste ready, no pseudocode.

import { Client } from '@reddb/client'

const db = new Client({ url: process.env.REDDB_URL })

// Auto-embed on insert — the engine calls the embedding provider
await db.query(
  `INSERT INTO articles (id, title, body)
   VALUES ($1, $2, $3)
   WITH AUTO EMBED (body) USING openai`,
  [1, 'RedDB vectors', 'Vector search and relational SQL in one engine.'],
)

// Similarity search — returns nearest neighbours by cosine distance
const { rows } = await db.query(
  `SEARCH SIMILAR TO $1 IN articles
   USING HNSW LIMIT 5`,
  ['how does vector search work'],
)
console.log(rows.map((r) => r.title))

Use cases

Where vectors earn their place.

  • RAG over docs

    Customer support, internal wikis, product docs — semantic retrieval without a Pinecone sync job.

  • Anomaly clustering

    Group similar logs / transactions / support tickets without a labelled training set.

  • Recommendations

    User-to-product or product-to-product similarity stored next to the relational facts you join on.

  • Deduplication

    Find near-duplicate rows that exact-match indexes don't catch (typos, formatting differences).

Build it

End-to-end walkthrough.

Four steps from empty database to a real vectors workload — each step shows the exact code and explains what the engine is doing.

  1. Step 1

    1. Create the vector collection

    Declare the vector column with its dimension matching your embedding model (1536 for OpenAI ada-002, 768 for many sentence-transformers). The IVF index is tunable per workload — lists = sqrt(rows) is a sane starting point.

    CREATE TABLE notes (
      id     UUID PRIMARY KEY DEFAULT gen_uuid(),
      body   TEXT NOT NULL,
      meta   JSONB,
      vec    VECTOR(1536)
    );
    
    CREATE INDEX idx_notes_vec ON notes
      USING IVFFLAT (vec) WITH (lists = 100);
  2. Step 2

    2. Auto-embed on insert

    WITH AUTO EMBED calls your configured embedding provider on the text columns listed in parentheses, populates the vec column at write time, and indexes it. You don't run a separate embedding pipeline.

    INSERT INTO notes (body, meta) VALUES
      ('suspicious vpn login from new country',
        '{"user_id":42,"severity":"high"}'),
      ('payment retry succeeded after 3 attempts',
        '{"user_id":42,"severity":"info"}')
    WITH AUTO EMBED (body) USING openai;
  3. Step 3

    3. Similarity search

    SEARCH SIMILAR TEXT embeds the query string with the same provider, runs k-NN against the index, and applies the WHERE filter post-retrieval. Hybrid filters (vector + structured) work in one statement — no two-system join.

    SEARCH SIMILAR TEXT 'login anomaly'
      COLLECTION notes
      WHERE meta->>'severity' = 'high'
      LIMIT 10;
  4. Step 4

    4. Hybrid search + RAG

    Hybrid search combines semantic similarity with traditional keyword scoring at configurable weights. WITH CONTEXT DEPTH 1 then expands each hit by 1 graph hop — the canonical RAG retrieval pattern, in one query.

    SEARCH HYBRID
      TEXT 'login anomaly'        WEIGHT 0.7
      KEYWORDS 'vpn,brute-force'  WEIGHT 0.3
      COLLECTION notes
      WITH CONTEXT DEPTH 1
      LIMIT 5;

Engine features

What RedDB adds on top of vectors.

The engine knobs you would otherwise wire up yourself — TTL, encryption, indexes, atomic ops, eventual consistency — applied to this data model.

  • Auto-embed on insert (8+ providers)

    WITH AUTO EMBED (col) USING <provider> resolves text to a vector at write time — OpenAI, Anthropic, Groq, OpenRouter, Together, Venice, DeepSeek, Ollama (or any OpenAI-compatible API). You don't run a separate embedding pipeline.

  • IVFFLAT + HNSW indexes

    Two index types: IVFFLAT is recall-tunable and cheap to rebuild; HNSW is faster on cold queries but more expensive to maintain. Pick per write/read ratio.

  • Hybrid retrieval (vector + keyword + filter)

    SEARCH HYBRID TEXT ... WEIGHT 0.7 KEYWORDS ... WEIGHT 0.3 WHERE meta->>... combines semantic similarity, BM25 keyword scoring, and structured filters in one statement. The optimiser plans the cheapest side first.

  • VectorRef typed pointers

    A RowRef-style typed column (VectorRef) constrains values to point at vector-collection items. Useful for "this product's recommendation seed lives in notes" cross-collection patterns.

  • Context expansion (vector + graph)

    SEARCH SIMILAR ... WITH CONTEXT DEPTH N runs vector retrieval, then expands each hit by N graph hops, returning the combined neighbourhood — the RAG retrieval shape natively.

  • TTL eviction

    Per-row WITH TTL lets the engine evict stale embeddings — useful when source content has a natural shelf life (news articles, time-bound recommendations).

  • Encryption at rest (Value::Secret metadata)

    Vector columns themselves are not encrypted (operations need to compute distance), but adjacent metadata columns (PII text, user identifiers) can be Value::Secret and auto-encrypt with the vault AES key.

  • Collection-scoped policies

    A policy can restrict SEARCH SIMILAR to a subset of collections per principal — e.g. customer support sees public_docs but not internal_engineering. The engine refuses the query at parse time.

  • Audit log of retrievals

    Every SEARCH SIMILAR can be audited with the query text, principal, and result IDs — useful for compliance ("who has searched for this content?") and debugging recommender drift.

Showcases

What vectors can do once you bring the rest of the engine in.

Cross-model correlation, algorithm flex, multi-model patterns — things that take a stack of services elsewhere.

Provider keys stay in the vault — never in your code

AUTO EMBED resolves $red.secret.openai.api_key from the vault on every insert. Application code never sees the key.

Set the provider key once via the secrets vault. Every AUTO EMBED USING openai reads it through the typed $secret reference internally — no env var to leak, no key in source, no .env in your repo. Rotate by updating the KV; running queries pick up the new value on next call.

sql

-- Once, by an authorised principal.
SET CONFIG red.secret.openai.api_key = 'sk-...';

-- Forever after, by any service.
INSERT INTO notes (body) VALUES ($1)
  WITH AUTO EMBED (body) USING openai;
-- Engine reads $red.secret.openai.api_key from vault as a typed Value.
-- Application code holds no key; logs hold no key; query plans hold no key.

-- Hybrid retrieval same way.
SEARCH HYBRID
  TEXT $1                 WEIGHT 0.7
  KEYWORDS $2             WEIGHT 0.3
  COLLECTION docs
  USING openai            -- vault-resolved
  LIMIT $config.acme.rag.contextSize;

Cross-model RAG: vector + graph + table in one round trip

Semantic retrieval, graph context expansion, relational facts, all in one query.

User asks 'who owns passport AB1234567 and what services do they use?'. The engine vector-searches notes for semantic context, expands each hit by 1 graph hop (OWNS / USES edges), joins to the relational users + services tables, and returns the assembled context — ready for the LLM. No retrieval orchestrator service.

sql

WITH ctx AS (
  SEARCH SIMILAR TEXT 'who owns passport AB1234567 and what services'
    COLLECTION notes
    WITH CONTEXT DEPTH 2
    LIMIT 5
)
SELECT
  u.name           AS owner,
  s.name           AS service,
  s.tier,
  c.note_excerpt,
  c.score          AS relevance
FROM ctx c
LEFT JOIN users    u ON u.id::text = c.connected_node_id
                     AND c.connected_kind = 'user'
LEFT JOIN services s ON s.id::text = c.connected_node_id
                     AND c.connected_kind = 'service';

Auto-embed + hybrid + filter at ingestion scale

High-cardinality batch ingest with automatic embedding, no Pinecone sync.

Bulk insert 10k product records — auto-embed runs against your configured provider in batches, the IVF index is updated, structured filters and BM25 keyword scoring all stay queryable in the same statement.

sql

INSERT INTO products (sku, title, description, meta)
SELECT sku, title, description, meta
FROM staging_products
WITH AUTO EMBED (title, description) USING openai
ON CONFLICT (sku) DO UPDATE
  SET title       = EXCLUDED.title,
      description = EXCLUDED.description,
      vec         = EXCLUDED.vec;

-- Hybrid search the next minute.
SEARCH HYBRID
  TEXT       'lightweight running shoes for trails'  WEIGHT 0.7
  KEYWORDS   'trail,waterproof,running'              WEIGHT 0.3
  COLLECTION products
  WHERE meta->>'in_stock' = 'true'
    AND (meta->>'price')::numeric < 200
  LIMIT 20;

Migrate from

Bring vectors over from your current tool.

From

Pinecone

Stream Pinecone vectors via fetch-by-id, write them straight into a RedDB collection. Auto-embed kicks in for any new rows.

red migrate vectors \
  --from "pinecone://<index>?namespace=prod" \
  --to   "reds://admin@<db>.<org>.db.reddb.io:5050" \
  --collection notes \
  --batch-size 1000

From

pgvector

A vector(N) column already maps cleanly. SELECT INTO across the wire — no re-embedding required.

INSERT INTO notes (id, body, vec)
SELECT id, body, embedding::vector(1536)
FROM postgres_export.notes;

Recipes

Common patterns, real driver code.

sql

Semantic search over a knowledge base

Embed at insert, retrieve by similarity, filter by metadata in one query.

SEARCH SIMILAR TEXT 'how do I rotate api keys?'
  COLLECTION docs
  WHERE meta->>'product' = 'cloud'
    AND meta->>'visibility' = 'public'
  LIMIT 5;

typescript

Hybrid retrieval for RAG

Combine semantic + keyword scoring at configurable weights, expand by graph context, ship to the LLM.

const ctx = await db.query(`
  SEARCH HYBRID
    TEXT $1               WEIGHT 0.7
    KEYWORDS $2           WEIGHT 0.3
    COLLECTION docs
    WITH CONTEXT DEPTH 1
    LIMIT 8
`, [userQuestion, keywordsFromQuestion(userQuestion)])

const answer = await llm.complete({
  system: 'Answer using only the provided context.',
  context: ctx.rows,
  user: userQuestion,
})

python

Near-duplicate detection

Find records that look semantically identical (typos, formatting differences) that exact-match indexes miss.

from reddb import connect

db = connect("reds://admin@.../my-db:5050")

dupes = db.query("""
  SEARCH SIMILAR TEXT $1 COLLECTION customer_records
  WHERE id <> $2
  LIMIT 10
""", [record.full_name, record.id])

near = [r for r in dupes if r.score > 0.92]

Limits

What it does. What it costs.

Operational caps and durability semantics, no hand-waving.

Vector dimensions
64–4096 (OpenAI ada-002 = 1536)
Index types
IVFFLAT (recall-tunable) and HNSW (faster cold queries)
Embedding providers
Any OpenAI-compatible API (8+ presets)
Hybrid query depth
Vector + keyword + filter + graph in one statement
Throughput
~241k bulk ops/sec on commodity hardware (gRPC)

When NOT to use

Don't pick vectors for these.

Honest constraints — when another model fits better.

  • Don't auto-embed body fields that are 100s of MB

    Embedding cost scales with token count. Chunk + summarise long documents application-side before letting AUTO EMBED hit the provider.

  • Avoid mixing dimensions in one collection

    A collection holds one fixed dimension. Pick OpenAI 1536 OR sentence-transformers 768 — not both. Provider migrations require re-embedding everything.

  • Don't store embeddings without the source text

    You will want to re-embed when the model changes. Keep the original text in the same row so a re-embed is a single UPDATE, not a join across systems.

vs

How RedDB vectors compare.

Pinecone

Vector storage on the same engine as your other data. No 'eventual sync', no ID drift, no separate billing.

pgvector

Auto-embed on insert is built-in. You don't write the embedding pipeline yourself.

FAQ

Questions teams ask before they pick vectors.

Which embedding providers are supported?

Any OpenAI-compatible API. We ship presets for OpenAI, Anthropic, Groq, OpenRouter, Together, Venice, DeepSeek, and Ollama. The USING <provider> clause picks one; USING custom lets you point at any compatible endpoint.

IVF or HNSW?

Both. USING IVFFLAT is recall-tunable and great for batch insert workloads; USING HNSW is faster on cold queries but more expensive to rebuild. Pick based on your write/read ratio.

Can I store the embedding myself instead of auto-embedding?

Yes. WITH AUTO EMBED is convenience; you can also write the vec column directly with a vector literal or via the binary protocol. Useful when your embedding pipeline already exists.

What about multimodal — images, audio?

Same shape: any embedding provider that returns a fixed-dimension vector works. The text-vs-image distinction lives in your provider config, not the engine.

How does this differ from running pgvector?

Mostly the auto-embed pipeline and the hybrid graph + vector search. pgvector gives you the index and the operators; you bring the embedding job, the keyword scorer, and the graph database for context expansion. RedDB ships those.

Try vectors on RedDB.

Free nano database, no credit card. AGPL self-host or managed Cloud — same engine, same file format.