惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Palo Alto Networks Blog
大猫的无限游戏
大猫的无限游戏
Martin Fowler
Martin Fowler
GbyAI
GbyAI
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
量子位
T
The Blog of Author Tim Ferriss
Y
Y Combinator Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
CERT Recently Published Vulnerability Notes
Recent Announcements
Recent Announcements
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
P
Privacy International News Feed
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
博客园 - 叶小钗
L
Lohrmann on Cybersecurity
G
GRAHAM CLULEY
T
The Exploit Database - CXSecurity.com
Hugging Face - Blog
Hugging Face - Blog
P
Proofpoint News Feed
NISL@THU
NISL@THU
博客园 - Franky
C
Cybersecurity and Infrastructure Security Agency CISA
The Register - Security
The Register - Security
M
MIT News - Artificial intelligence
Know Your Adversary
Know Your Adversary
A
Arctic Wolf
F
Full Disclosure
T
Threat Research - Cisco Blogs
P
Privacy & Cybersecurity Law Blog
The Hacker News
The Hacker News
博客园 - 【当耐特】
D
Docker
T
Tailwind CSS Blog
S
SegmentFault 最新的问题
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Jina AI
Jina AI
Help Net Security
Help Net Security
V
Visual Studio Blog
小众软件
小众软件
B
Blog
Vercel News
Vercel News
云风的 BLOG
云风的 BLOG
N
News and Events Feed by Topic
Forbes - Security
Forbes - Security
N
Netflix TechBlog - Medium
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
C
Cisco Blogs
Security Archives - TechRepublic
Security Archives - TechRepublic

Supabase Blog

AI Agents Know About Supabase. They Don't Always Use It Right. Custom OIDC Providers for Supabase Auth 100,000 GitHub stars Supabase docs over SSH Navigating Regional Network Blocks Supabase Joins the Stripe Projects Developer Preview Log Drains: Now available on Pro Supabase Storage: major performance, security, and reliability updates Supabase incident on February 12, 2026 Hydra joins Supabase X / Twitter OAuth 2.0 is now available for Supabase Auth BKND joins Supabase Supabase is now an official Claude connector Supabase PrivateLink is now available Introducing: Postgres Best Practices When to use Read Replicas vs. bigger compute Introducing TRAE SOLO integration with Supabase Supabase Security Retro: 2025 Sync Stripe Data to Your Supabase Database in One Click Building ChatGPT Apps with Supabase Edge Functions and mcp-use Own Your Observability: Supabase Metrics API Introducing iceberg-js: A JavaScript Client for Apache Iceberg Introducing Supabase for Platforms Adding Async Streaming to Postgres Foreign Data Wrappers Build "Sign in with Your App" using Supabase Auth Introducing Seven New Email Templates for Supabase Auth The new Supabase power for Kiro Introducing Supabase ETL Introducing Analytics Buckets Introducing Vector Buckets Snap, Inc. Launches Snap Cloud, Powered by Supabase Triplit joins Supabase Supabase Series E 1000 Y Combinator Founders Choose Supabase gm 👋 web3, welcome aboard to Sign in with Web3 (Solana, Ethereum) Announcing the Supabase Remote MCP Server Enterprise speed, enterprise standards with Bolt Cloud + Supabase PostgREST 13 Lovable Cloud + Supabase: The Default Platform for AI Builders Processing large jobs with Edge Functions, Cron, and Queues Defense in Depth for MCP Servers OrioleDB Patent: now freely available to the Postgres community Supabase Launch Week 15 Hackathon Winner Announcement The Vibe Coder's Guide to Supabase Environments Testing for Vibe Coders: From Zero to Production Confidence The Vibe Coding Master Checklist Vibe Coding: Best Practices for Prompting Supabase Auth: Build vs. Buy Top 10 Launches of Launch Week 15 Supabase Launch Week 15 Hackathon Storage: 10x Larger Uploads, 3x Cheaper Cached Egress, and 2x Egress Quota Persistent Storage and 97% Faster Cold Starts for Edge Functions Algolia Connector for Supabase New Observability Features in Supabase Improved Security Controls and A New Home for Security Introducing Branching 2.0 Stripe-To-Postgres Sync Engine as standalone Library Supabase Analytics Buckets with Iceberg Support Create a Supabase backend using Figma Make Introducing JWT Signing Keys Supabase UI: Platform Kit Build a Personalized AI Assistant with Postgres Announcing Multigres: Vitess for Postgres Building on open table formats Open Data Standards: Postgres, OTel, and Iceberg Simplifying back-end complexity with Supabase Data APIs PostgreSQL Event Triggers without superuser access Top 10 Launches of Launch Week 14 Supabase MCP Server Data API Routes to Nearest Read Replica Declarative Schemas for Simpler Database Management Realtime: Broadcast from Database Keeping Tabs on What's New in Supabase Studio Edge Functions: Deploy from the Dashboard + Deno 2.1 Introducing the Supabase UI Library Supabase Auth: Bring Your Own Clerk Postgres Language Server: Initial Release Migrating from Fauna to Supabase Migrating from the MongoDB Data API to Supabase Dedicated Poolers Postgres as a Graph Database: (Ab)using pgRouting AI Hackathon at Y Combinator Calendars in Postgres using Foreign Data Wrappers Supabase Launch Week 13 Hackathon Winners How to Hack the Base! Running Durable Workflows in Postgres using DBOS database.build v2: Bring-your-own-LLM Restore to a New Project Hack the Base! with Supabase Top 10 Launches of Launch Week 13 Supabase Queues High Performance Disk Supabase Cron Supabase CLI v2: Config as Code Supabase Edge Functions: Introducing Background Tasks, Ephemeral Storage, and WebSockets Supabase AI Assistant v2 OrioleDB Public Alpha Executing Dynamic JavaScript Code on Supabase with Edge Functions ClickHouse Partnership, improved Postgres Replication, and Disk Management Live Share: Connect to in-browser PGlite with any Postgres client
Automatic Embeddings in Postgres
Greg Richardson · 2025-04-01 · via Supabase Blog

Automatic Embeddings in Postgres

Today we’re releasing automatic embeddings - automate embedding generation and updates using Supabase Vector, Queues, Cron, and pg_net extension, and Edge Functions.

Embeddings power features like semantic search, recommendations, and retrieval-augmented generation (RAG). They represent text or other content as high-dimensional vectors. At query time, you convert the input into a vector and compare it to stored vectors to find similar items.

Postgres with pgvector already supports storing and searching over vectors. But generating and maintaining those embeddings has been left to the application. This often means building a separate pipeline just to keep vector data in sync.

Automatic embeddings bring that pipeline into the database. You can manage embedding generation using SQL, triggers, and extensions like pgmq, pg_cron, and pg_net. No new runtimes or services are required.

Most teams implementing semantic features in Postgres end up building their own pipeline. The general pattern looks like this:

  1. Store source content (e.g. documents, tickets, articles)
  2. Generate an embedding using an external model
  3. Store the result in a vector column
  4. Re-run the embedding job if the content changes
  5. Handle retries if the model fails or times out

This pipeline is easy to describe but hard to implement. It introduces inconsistency between your source of truth (Postgres) and derived data (the embeddings). It also requires background workers, queues, observability, and external coordination.

Here are some ways this pipeline can fall apart:

  • Drift. If you update the content but forget to re-embed it, your search quality drops.
  • Latency. Some embedding APIs are slow or rate-limited. If you call them synchronously on write, you add latency to the write path.
  • Lack of resilience. If your background worker dies or the queue fails, you may not notice until things break.
  • Schema duplication. Your application ends up duplicating logic that could live in the schema.

Automatic embeddings move the vector generation step into Postgres. Not literally. Inference still happens via an external model, but the responsibility for coordinating that process becomes part of your database.

When a row is inserted or updated, Postgres can automatically enqueue a job to generate or refresh its embedding. That job runs in the background, retries if it fails, and stores the result back into the vector column.

This approach has a few benefits:

  • No drift. Embeddings stay in sync with content updates.
  • Bring your own model. You can point to any API that returns a vector.
  • All SQL. You can enqueue, inspect, and retry embedding jobs without leaving Postgres.

A number of use cases get easier when embeddings are automatically managed:

  • Build semantic search without leaving SQL
  • Keep embeddings fresh as data changes
  • Use vector search for deduplication or anomaly detection
  • Combine structured and semantic filters in a single query
  • Enrich or classify rows using embedding-based inheritance

There are two approaches to automatic embeddings today:

Generated columns#


_10

create table documents (

_10

id uuid primary key,

_10

content text,

_10

embedding vector(1536) generated always as (embed(content)) stored

_10

);


This uses a generated column to call an embedding function on write. It only works if your model is local and fast. In practice, this approach with the embed() function blocks the write path and doesn’t scale well.

Trigger-based asynchronous embeddings#

This is the pattern we use at Supabase. It uses a few common extensions:

  • SQL triggers to enqueue work when rows are inserted or updates
  • pgmq to enqueue embedding jobs inside a transactional message queue
  • pg_net to send async HTTP requests to an Edge Function (and in turn, embedding provider like OpenAI)
  • pg_cron to run workers that process the queue
  • pgvector for storing and searching over embeddings

You can inspect the queue, retry failed jobs, and customize the Edge Function used to generate embeddings. You can find the complete reference implementation in the Supabase Automatic Embeddings Guide.

After applying the implementation from the guide, it is as easy as adding two triggers to a table.

Set up the table#

First let’s create a documents table with an embedding column to store the vector.


_11

-- Table to store documents with embeddings

_11

create table documents (

_11

id integer primary key generated always as identity,

_11

title text not null,

_11

content text not null,

_11

embedding halfvec(1536),

_11

created_at timestamp with time zone default now()

_11

);

_11

_11

-- Index for vector search over document embeddings

_11

create index on documents using hnsw (embedding halfvec_cosine_ops);


Create the embedding pipeline#

Next we create an embedding_input function that tells the embedding generator what to use as the source content:


_11

-- Customize the input for embedding generation

_11

-- e.g. Concatenate title and content with a markdown header

_11

create or replace function embedding_input(doc documents)

_11

returns text

_11

language plpgsql

_11

immutable

_11

as $$

_11

begin

_11

return '# ' || doc.title || E'\n\n' || doc.content;

_11

end;

_11

$$;


This is useful for many embedding pipelines where you want your embedding to represent a combination of multiple text columns like title + content instead of a single column.

Finally we add two triggers:


_13

-- Trigger for insert events

_13

create trigger embed_documents_on_insert

_13

after insert

_13

on documents

_13

for each row

_13

execute function util.queue_embeddings('embedding_input', 'embedding');

_13

_13

-- Trigger for update events

_13

create trigger embed_documents_on_update

_13

after update of title, content -- must match the columns in embedding_input()

_13

on documents

_13

for each row

_13

execute function util.queue_embeddings('embedding_input', 'embedding');


These ensure that embeddings are updated for both new records (inserts) and modified records (updates). Note that these triggers fire off “embedding jobs” that run asynchronously instead of blocking the write path with a long-running operation.

Under the hood, pg_cron will batch embedding jobs at an interval and send them off to an Edge Function to perform the actual embedding generation. The default generation logic looks something like this:


_14

/**

_14

* Generates an embedding for the given text.

_14

*/

_14

async function generateEmbedding(text: string) {

_14

const response = await openai.embeddings.create({

_14

model: 'text-embedding-3-small',

_14

input: text,

_14

})

_14

const [data] = response.data

_14

if (!data) {

_14

throw new Error('failed to generate embedding')

_14

}

_14

return data.embedding

_14

}


But you can adjust this to use any inference API and model that you prefer.

Generate automatic embeddings and query the table#

Now, you can insert a new document into your table:


_10

insert into documents (title, content)

_10

values

_10

('Understanding Vector Databases', 'Vector databases are specialized...');


This will kick off the embedding pipeline within a Supabase Edge Function. If you were to immediately query for the document you just inserted, the embedding column will be empty:


_10

select id, embedding

_10

from documents

_10

where title = 'Understanding Vector Databases';


However, if you were to retry in a few seconds, the embedding column will be populated correctly. This is because the pipeline is asynchronous and the Edge Function will be working in the background to generate the embedding and store it properly.

Similarly, if you were to come back and update the row you added to the documents table, at first the embedding column will be null because the trigger initially resets it. The trigger also queues up the Edge Function that will generate and populate the embedding column, which should complete within seconds. This keeps your data and its associated embedding in sync.

You can get started with automatic embeddings today: