---
title: "Pixeltable vs pgvector: pipeline vs a Postgres vector column"
description: "pgvector puts vectors in Postgres you already run. Pixeltable keeps embeddings on the source row with media and HTTP. Not a vector database. Keep pgvector when SQL and HNSW are the product."
keywords:
  - Pixeltable vs pgvector
  - pgvector alternative
  - Postgres vector search
  - HNSW Postgres
  - embedding index
  - RAG Python
url: "https://www.pixeltable.com/compare/pixeltable-vs-pgvector"
---

# Pixeltable and pgvector

Updated: 2026-10-28

## Which is better, Pixeltable or pgvector?

It depends. Pixeltable belongs when media, computed columns, and an embedding index should live on the source row and stay current on insert. pgvector belongs when you already run Postgres, want SQL joins and ACID around vectors, or need HNSW or IVFFlat you tune yourself. Pixeltable is not a vector database. Keep pgvector in the database you already operate. As of 2026-10-28.

pgvector is a Postgres extension for vector similarity search: a vector column, L2, inner-product, or cosine operators, and HNSW or IVFFlat indexes. Pixeltable is not a vector database. It is the application schema around one: typed media, computed columns, EmbeddingIndex, and HTTP in one Python file. Keep pgvector in the Postgres you already operate; use Pixeltable when the pipeline around the vector is the product.

## Summary

### Pixeltable

- Chunking, embeddings, and similarity live on the table
- Insert and delete keep the index current, no upsert job
- Source media stays queryable next to the vector
- HTTP from the same file if you declare FastAPIRouter

### pgvector

- vector, halfvec, bit, and sparsevec types in Postgres you already run
- Exact search, or HNSW or IVFFlat approximate indexes you tune
- JOINs, ACID, point-in-time recovery, any Postgres client
- You still generate embeddings, chunk files, and serve HTTP yourself

## Comparison

| Feature | Pixeltable | pgvector |
| --- | --- | --- |
| What it is | Tables + computed columns + EmbeddingIndex | Postgres extension for vector similarity search |
| Keeping vectors in sync | Index is schema; insert, delete, and update recompute the affected rows | You embed and INSERT or UPDATE; a failed embed job is a row you repair |
| Source media | Document, Image, Video, Audio columns next to the index | bytea, text, or a URL you store; bytes live in S3 or on disk unless you add that |
| SQL and ACID | Catalog on Postgres; you do not write the JOIN or the HNSW DDL | Native SQL, JOINs, transactions, backups, extensions you already operate |
| ANN inside Postgres | EmbeddingIndex on the catalog; not HNSW or IVFFlat you tune with lists and probes | HNSW or IVFFlat, m, ef_construction, probes, exact search with no index |
| Glue around it | One schema | Chunker + embedder + orchestrator + FastAPI, unless you already have them |
| Ops you already know | pxt schema update and pxt service update; a different operational model | CREATE EXTENSION vector; the Postgres you already back up |

## Document search

Pixeltable: document_splitter view and EmbeddingIndex. Query with similarity(string=), then order_by. Apply with pxt schema update app.py search. pgvector: CREATE EXTENSION, a vector column, HNSW, ORDER BY embedding <-> query. From github.com/pgvector/pgvector (accessed 2026-10-28). You still embed the document and the query yourself.

### Pixeltable

```python
import pixeltable as pxt
from pixeltable.functions.document import document_splitter
from pixeltable.functions.huggingface import sentence_transformer

TableModel = pxt.model_base()
embed = sentence_transformer.using(
    model_id='sentence-transformers/all-MiniLM-L6-v2'
)

class Docs(TableModel, name='docs'):
    document: pxt.Document
    title: pxt.String

class Chunks(
    TableModel,
    name='chunks',
    base=Docs,
    iterator=document_splitter(
        Docs.document, separators='sentence,token_limit', limit=512
    ),
):
    __indexes__ = [pxt.EmbeddingIndex(text, embedding=embed)]

if __name__ == '__main__':
    # After: pxt schema update app.py search
    docs = pxt.get_table('search.docs')
    docs.insert([{'document': 'papers/ml.pdf', 'title': 'Research Paper'}])
    chunks = pxt.get_table('search.chunks')
    sim = chunks.text.similarity(string='machine learning algorithms')
    chunks.order_by(sim, asc=False).limit(10).select(chunks.text, chunks.title)
```

### pgvector

```sql
-- github.com/pgvector/pgvector
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE items (
  id bigserial PRIMARY KEY,
  title text,
  embedding vector(384)
);

CREATE INDEX ON items USING hnsw (embedding vector_l2_ops);

-- You still chunk the PDF and call an embedder in application code.
INSERT INTO items (title, embedding) VALUES (
  'Research Paper',
  '[0.1, 0.2, ...]'
);

SELECT id, title
FROM items
ORDER BY embedding <-> '[0.11, 0.19, ...]'
LIMIT 10;
```

## When to choose Pixeltable

- **RAG where the source row matters**: Documents, images, or video plus the embedding. Insert should update the index. You do not want a second upsert path beside Postgres.
- **You were about to glue Celery, Redis, and pgvector for a media app**: The call-intelligence showcase on GitHub measures that glue: 1,171 lines in 24 files for FastAPI + SQLAlchemy + Alembic + Celery + Redis + Postgres + pgvector, against 680 lines in 4 files for Pixeltable (compare/WHY_PIXELTABLE.md on main, accessed 2026-10-28). Line counts, not query latency.

## When to choose pgvector

- **Vectors belong in the Postgres you already run**: JOINs, ACID, backups, RLS, a client every language already has. Pixeltable does not replace Postgres for that job. README: github.com/pgvector/pgvector
- **ANN you tune is the binding constraint**: HNSW vs IVFFlat, lists, probes, ef_search, halfvec. This page does not claim Pixeltable wins a recall/latency bake-off. pgvector publishes those knobs; we did not rerun them.

## Making the right choice

### Do not over-claim

- Pixeltable is not a vector database and not a Postgres replacement.
- The showcase numbers are source line counts and operator steps from a published methodology, not ANN latency. How to rerun: github.com/pixeltable/showcase-call-intelligence (METHODOLOGY.md). We did not rerun it in this change.
- That same page says where the Reference (pgvector) is ahead: Celery can process calls in parallel; a Pixeltable insert holds the table lock, so inserts into one table run one at a time. Status during processing is also more visible on the Reference.
- No Pixeltable vs pgvector query-latency benchmark is on this page.
- Supabase, Neon, and Prisma compare pages cover hosted Postgres. This page is the extension.

## FAQ

### Is Pixeltable a pgvector alternative?

For app-scale RAG where the source row matters, it can replace the glue around pgvector (chunking, embed jobs, HTTP). It does not replace pgvector inside Postgres. Keep pgvector when SQL, JOINs, and HNSW you tune are the product.

### Is Pixeltable a vector database?

No. EmbeddingIndex is declared on a table that also holds source media and computed columns. pgvector is the vector type and the ANN index in Postgres. Different layer.

### Can I use Pixeltable with pgvector?

Yes. Pixeltable can remain the system of record; export embeddings if pgvector is already the serving contract in your database. Complementary, not a requirement.

### What about Neon, Supabase, and Pinecone?

Neon and Supabase are hosted Postgres (they can run pgvector). Pinecone is a managed ANN service. This page is the extension. See /compare/pixeltable-vs-neon, /compare/pixeltable-vs-supabase, and /compare/pixeltable-vs-pinecone.

