K3 Vector Preview

Search by meaning. On rows you already trust.

A vector is just a column in your table. Index it, then filter, join and sort the results with the SQL you already write. No second database to feed, no copy to keep in sync.

Start free ORDER BY embedding <=> :q
pgvector operators · five index kinds · exact distances
q =“what is the refund window for enterprise customers?”
SELECT id, title, embedding <=> :q AS distance
  FROM contracts
 WHERE tier = 'enterprise'
 ORDER BY distance LIMIT 3;
#1acme-msa-2026Refunds within 30 days…0.091
#2refund-policy-v3Enterprise refund terms…0.128
#3zenith-msa-2024Credits for disputed…0.233
Postgres wire · any driver
A vector is a column

Stop syncing a second database.

Most teams copy their rows into a vector store, then spend the next year keeping the copy honest. In K3 the embedding sits in the same row as the data it describes, so there is nothing to sync and nothing to drift.

Filter with WHERE, join to any table, page with LIMIT
Write the row and its vector in one transaction
Searchable the moment the write is acknowledged
Permissions and billing: the same as the table’s
contracts.sql
CREATE TABLE contracts (
  id        BIGINT PRIMARY KEY,
  title     VARCHAR,
  tier      VARCHAR,
  embedding VECTOR(1024)
);
CREATE INDEX ON contracts
  USING hnsw (embedding vector_cosine_ops);

BEGIN;
INSERT INTO contracts VALUES (42, 'acme-msa-2026', 'enterprise', :emb);
UPDATE accounts SET contract_id = 42 WHERE id = :acct;
COMMIT;  -- the row, its vector and the link land together
Accuracy at scale

Recall that doesn’t fall off a cliff.

Graph indexes quietly lose accuracy as a collection grows. K3’s quantized HNSW holds its recall from twenty thousand to two hundred thousand vectors at 768 dimensions, where a plain graph over the same rows drops below half.

≥ 0.987recall@10 with hnsw_sq_f16, from 20k to 200k vectors
recall@10 at 200,000 × 768, against exact search
K3 hnsw_sq_f160.987
Unquantized HNSW on the same rows0.434
Under about 20,000 vectors every K3 index kind measures 0.99 or better. Clustered corpora standing in for real embeddings, serve defaults.
What you can count on

Built so a search result is never a guess.

Exact distances, always

An index only picks candidates. Every result is re-ranked at full precision, so the distance you see is the true one, quantized index or not.

No vector silently lost

Every build proves every stored vector reachable, or it fails and tells you. A quietly lossy index can’t exist.

Fresh by default

Search sees your latest writes. If an index is catching up, K3 answers exactly instead of serving stale results.

Filters that keep their promise

WHERE plus nearest-neighbour never comes back short: K3 widens the search, or scans exactly, until the page is full.

Five index kinds, one CREATE INDEX.

Pick per column with plain pgvector syntax. Build in the background with WITH (async) and watch it with SHOW VECTOR INDEXES.

hnswThe default. Under ~20k vectors it builds fastest and measures ≥ 0.99.
hnsw_sq_f16Large collections at embedding dimensions. Holds ≥ 0.987 to 200k.
hnsw_sq_i8Smallest graph. Refused on inner-product columns, with f16 named instead.
ivfflatWell-clustered data; tune recall with ivfflat.probes.
ivf_sq8About a quarter of ivfflat’s size, with the same measured recall.
Keep your code

Ask in SQL, or the API you already use.

Every door reaches the same column and returns the same ranking. Moving off a hosted vector database is a change of address, not a rewrite.

Postgres
pg.uk-lon-1.dodil.io:5432
Qdrant APIPreview
qdrant.uk-lon-1.dodil.io
Pinecone APIPreview
pinecone.uk-lon-1.dodil.io
GraphQLPreview
gql.uk-lon-1.dodil.io/graphql
SELECT id, title
  FROM contracts
 WHERE tier = 'enterprise'
 ORDER BY embedding <=> :q
 LIMIT 5;
The Qdrant and Pinecone APIs return distances, so lower is closer. Pinecone calls name the table with an X-Dodil-Index header.
Vectors over Postgres. Your ORM just works.
Work out of the box, tested by a conformance suite
SQLAlchemyDjangoAlembicPrismaGORMSQLxpsycopgnode-postgres
Plus the standard Postgres drivers: pgx, pgJDBC, asyncpg, Npgsql.
What people build

One table type. Four jobs.

RAG on your records

Retrieve the paragraphs that answer the question, filtered to the customer asking, and hand them to your model with the row ids as citations.

Search with business rules

Meaning plus WHERE: only this region, only signed contracts, only what this user may see. One query, no post-filtering in app code.

Agent memory

Store what an agent learned as rows with embeddings, recall the closest memories by meaning, and join them to the facts they refer to.

Embed on upload

Attach an embedding template to a bucket and every file that lands is chunked and embedded into a vector table for you.

What Preview means

Know the edges before you build.

  • Vector search is in Preview: the SQL surface and guarantees above are stable, and we keep widening them.
  • The Qdrant and Pinecone APIs cover search and upsert. Creating and describing collections happens in SQL or the console.
  • String ids are searched exactly rather than through the index. Integer ids use the index.
  • K3 doesn’t create embeddings inside a query. Use an embedding template on upload, or bring vectors from your model.
Coming
Hybrid search

Keyword and meaning ranked together in one query.

Coming
Python stores on PyPI

LangChain and LlamaIndex vector stores for K3, one pip install away.

Add a vector column. Search it tonight.

Same bucket, same SQL, same bill as the rest of your data. Free to start, no card.

Regions
UK · LondonliveEU · FrankfurtnextMiddle EastsoonAfricasoon
Compliance
SOC 2in progressISO 27001in progressGDPR-readyData residencyenforced
© 2026 Circle Technologies Pte Ltd. All rights reserved.