Vectorizer and in-database LLM calls migration guide
Plan your move off Tiger Cloud-managed vectorizer workers and in-database LLM SQL helpers before June 30, 2026. Tables, embeddings, and vectorizer definitions stay in the database.
This guide is for Tiger Cloud (AWS and Azure). It does not apply to self-hosted deployments that never used Tiger Cloud-managed vectorizer scheduling.
The following AI capabilities are deprecated on Tiger Cloud and will be removed on June 30, 2026:
- Managed vectorizer: the Tiger Cloud-managed service that ran vectorizer workers for you. Your vectorizer definitions and embedding tables stay in place; you run the vectorizer worker yourself (see Migrate the vectorizer).
- In-database LLM calls: SQL-callable helpers such as
ai.openai_embed,ai.openai_chat_complete,ai.anthropic_generate,ai.ollama_embed,ai.cohere_embed, and relatedai.*entry points. These will no longer be available from SQL.
Your data is not affected. Tables, embeddings, and vectorizer configuration remain in the database. Only Tiger Cloud-managed execution of the worker and the in-database LLM call surface are going away.
What is not changing: Semantic search with pgvector and pgvectorscale, and keyword search with BM25 via pg_textsearch, stay available on Tiger Cloud. Those are still the building blocks for hybrid search.
Upgrade the extension
Section titled “Upgrade the extension”In pgai v0.10.0, vectorizer code moved out of the ai extension into the standalone pgai Python package. On extension versions 0.4.0 through 0.9.x, vectorizer SQL objects still belong to the extension. Upgrade the extension before you follow the worker migration below.
1. check your current pgai version
Section titled “1. check your current pgai version”SELECT extversion FROM pg_extension WHERE extname = 'ai';If the result is 0.9.x or earlier, complete the upgrade steps below. If it is 0.10.0 or later, skip to Migrate the vectorizer.
2. upgrade pgai to the latest version
Section titled “2. upgrade pgai to the latest version”ALTER EXTENSION ai UPDATE;This migration detaches vectorizer objects from the extension without dropping them. Definitions and data stay intact.
3. install the pgai library for ongoing vectorizer management
Section titled “3. install the pgai library for ongoing vectorizer management”pip:
pip install "pgai[vectorizer-worker]"pgai install -d "postgres://tsdbadmin:<password>@<host>:<port>/tsdb?sslmode=require"Docker:
docker run --pull always --rm --entrypoint python \ timescale/pgai-vectorizer-worker:latest \ -m pgai install -d "postgres://tsdbadmin:<password>@<host>:<port>/tsdb?sslmode=require"After these steps, continue with Migrate the vectorizer.
Migrate the vectorizer
Section titled “Migrate the vectorizer”1. disable cloud scheduling
Section titled “1. disable cloud scheduling”Connect to your database and remove the cloud scheduler from your vectorizers. This deletes the TimescaleDB background jobs and sets scheduling to none, while leaving vectorizers enabled so your self-hosted worker can process them:
-- Delete the TimescaleDB scheduled jobsSELECT public.delete_job((config->'scheduling'->>'job_id')::int)FROM ai.vectorizerWHERE config->'scheduling'->>'implementation' = 'timescaledb';
-- Switch scheduling to noneUPDATE ai.vectorizerSET config = jsonb_set(config, '{scheduling}', '{"config_type": "scheduling", "implementation": "none"}'::jsonb)WHERE config->'scheduling'->>'implementation' = 'timescaledb';2. get your connection string
Section titled “2. get your connection string”Copy your Tiger Cloud connection string from Tiger Console. It looks like:
postgres://tsdbadmin:<password>@<host>:<port>/tsdb?sslmode=require3. run the vectorizer worker
Section titled “3. run the vectorizer worker”Pick one of the following.
Option A: Docker (recommended)
Section titled “Option A: Docker (recommended)”Create a .env file with your API keys:
OPENAI_API_KEY=sk-your-openai-api-keyRun the worker:
docker run \ --env-file .env \ timescale/pgai-vectorizer-worker:latest \ --db-url "postgres://tsdbadmin:<password>@<host>:<port>/tsdb?sslmode=require" \ --poll-interval 5m \ -c 4Option B: Docker Compose
Section titled “Option B: Docker Compose”name: pgai-vectorizerservices: vectorizer-worker: image: timescale/pgai-vectorizer-worker:latest environment: PGAI_VECTORIZER_WORKER_DB_URL: "postgres://tsdbadmin:<password>@<host>:<port>/tsdb?sslmode=require" OPENAI_API_KEY: "sk-your-openai-api-key" command: ["--poll-interval", "5m", "-c", "4"] restart: unless-stoppedStart it:
docker compose up -dOption C: CLI
Section titled “Option C: CLI”pip install pgai[vectorizer-worker]export OPENAI_API_KEY=sk-your-openai-api-keypgai vectorizer worker -d "postgres://tsdbadmin:<password>@<host>:<port>/tsdb?sslmode=require" --poll-interval 5m -c 4Option D: Python
Section titled “Option D: Python”import asynciofrom datetime import timedelta
from pgai import Worker
worker = Worker( db_url="postgres://tsdbadmin:<password>@<host>:<port>/tsdb?sslmode=require", poll_interval=timedelta(minutes=5), concurrency=4,)asyncio.run(worker.run())Full worker options: pgai vectorizer worker documentation.
Migrate away from in-database LLM calls
Section titled “Migrate away from in-database LLM calls”Move provider calls into application code. Keep using PostgreSQL for storage and vector search; generate embeddings and completions outside the database, then pass vectors or text into SQL as parameters.
Migrate embedding calls
Section titled “Migrate embedding calls”Before (embedding inside the database):
SELECT id, contentFROM documentsORDER BY embedding <=> ai.openai_embed('text-embedding-3-small', 'search query')LIMIT 5;After (embedding in Python, vector as a query parameter):
import openaiimport psycopg2
client = openai.OpenAI() # uses OPENAI_API_KEY env var
def semantic_search(query: str, limit: int = 5): response = client.embeddings.create( model="text-embedding-3-small", input=query, ) embedding = response.data[0].embedding
conn = psycopg2.connect("postgres://tsdbadmin:<password>@<host>:<port>/tsdb?sslmode=require") cur = conn.cursor() cur.execute( """ SELECT id, content FROM documents ORDER BY embedding <=> %s::vector LIMIT %s """, (embedding, limit), ) return cur.fetchall()With asyncpg, bind the embedding the way your driver and pgvector build expect (for example a string literal for vector or a supported sequence type):
import openaiimport asyncpg
client = openai.OpenAI()
async def semantic_search(query: str, limit: int = 5): response = client.embeddings.create( model="text-embedding-3-small", input=query, ) embedding = response.data[0].embedding
conn = await asyncpg.connect("postgres://tsdbadmin:<password>@<host>:<port>/tsdb?sslmode=require") rows = await conn.fetch( """ SELECT id, content FROM documents ORDER BY embedding <=> $1::vector LIMIT $2 """, str(embedding), limit, ) return rowsMigrate chat completion calls
Section titled “Migrate chat completion calls”Before:
SELECT ai.openai_chat_complete( 'gpt-4o', jsonb_build_array( jsonb_build_object('role', 'user', 'content', 'Summarize this: ' || doc.content) ))->'choices'->0->'message'->>'content' AS summaryFROM documents docWHERE doc.id = 1;After:
import openai
client = openai.OpenAI()
def summarize(content: str) -> str: response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": f"Summarize this: {content}"}], ) return response.choices[0].message.contentMigrate Anthropic calls
Section titled “Migrate Anthropic calls”Before:
SELECT ai.anthropic_generate( 'claude-sonnet-4-20250514', jsonb_build_array( jsonb_build_object('role', 'user', 'content', 'Explain this concept') ));After:
import anthropic
client = anthropic.Anthropic()
def generate(prompt: str) -> str: message = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, messages=[{"role": "user", "content": prompt}], ) return message.content[0].textMigrate Cohere reranking
Section titled “Migrate Cohere reranking”Before:
SELECT ai.cohere_rerank( 'rerank-english-v3.0', 'search query', jsonb_agg(content))FROM documentsLIMIT 100;After:
import cohere
client = cohere.Client()
def rerank(query: str, documents: list[str]) -> list: response = client.rerank( model="rerank-english-v3.0", query=query, documents=documents, ) return response.resultsSummary of function replacements
Section titled “Summary of function replacements”| Deprecated function | Replacement |
|---|---|
ai.openai_embed(model, text) | openai.OpenAI().embeddings.create(model=model, input=text) |
ai.openai_chat_complete(model, messages) | openai.OpenAI().chat.completions.create(model=model, messages=messages) |
ai.openai_chat_complete_simple(model, prompt) | openai.OpenAI().chat.completions.create(model=model, messages=[...]) |
ai.openai_moderate(model, input) | openai.OpenAI().moderations.create(model=model, input=input) |
ai.anthropic_generate(model, messages) | anthropic.Anthropic().messages.create(model=model, messages=messages) |
ai.ollama_embed(model, text) | ollama.embed(model=model, input=text) |
ai.ollama_generate(model, prompt) | ollama.generate(model=model, prompt=prompt) |
ai.ollama_chat_complete(model, messages) | ollama.chat(model=model, messages=messages) |
ai.cohere_embed(model, text) | cohere.Client().embed(model=model, texts=[text]) |
ai.cohere_rerank(model, query, docs) | cohere.Client().rerank(model=model, query=query, documents=docs) |
ai.cohere_chat_complete(model, messages) | cohere.Client().chat(model=model, messages=messages) |
ai.voyageai_embed(model, text) | voyageai.Client().embed(texts=[text], model=model) |
ai.voyageai_rerank(model, query, docs) | voyageai.Client().rerank(query=query, documents=docs, model=model) |
General migration pattern
Section titled “General migration pattern”For any ai.* SQL function:
- Identify the provider from the name (
openai_,anthropic_,ollama_,cohere_,voyageai_). - Install that provider’s SDK (
pip install openai,pip install anthropic, and so on). - Call the SDK from your application before or after your SQL.
- Pass structured results as parameters (for embeddings, pass the vector into
ORDER BY ... <=> $1style queries).
Next steps
Section titled “Next steps”| Topic | Where to read |
|---|---|
| pgai SQL and vectorizer reference | pgai reference |
| Vector search concepts | Key vector concepts for pgvector |
| Tiger Cloud + pgvector overview | Understand pgvector and pgvectorscale |