Generated banner for Neon Postgres
Generated logo for Neon Postgres

Neon Postgres

NeonOfficialPublished by Neon

  • Skill
  • Tool integration
  • Data and AI
  • Apache-2.0
  • No issues found

From the author

Guides and best practices for working with Lakebase Postgres on Neon: connections, pooled vs direct, schema migrations, branching (including schema-only, reset-from-parent, and branch-per-PR workflows), autoscaling, scale-to-zero, instant restore, read replicas, IP allow lists, logical replication, egress optimization, and Lakebase Search. Use when the work is an existing DATABASE_URL, SQL, schema, inspect, or search. New backends, Auth, files, Functions, and LLM calls go to the parent `neon` skill. Live queries, reactive UIs, and realtime data go to `neon-realtime`. Also use for "@neondatabase/serverless", "@neon/neon-js", "neon inspect db", "neon postgres computes", "Neon branch", "schema-only branch", "reset branch", "branch per PR", high database bills, network transfer or egress, SELECT * optimization, query overfetching, "semantic search", "vector search", "full-text search", "BM25", or "hybrid search".
— the description by Neon

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides guidance for working with Lakebase Postgres on Neon. It covers connection management, schema migrations, branching workflows, autoscaling, and performance diagnostics. It is designed to assist with database operations including inspecting schemas, optimizing egress, and implementing search features like vector, full-text, and hybrid search. The skill distinguishes between pooled and direct connection usage, provides diagnostic tools for performance analysis, and outlines procedures for managing compute resources and database branches.

What it does

  • Provides best practices for pooled versus direct connection usage
  • Guides schema migration and branching workflows including schema-only and branch-per-PR
  • Offers diagnostic tools for identifying egress anti-patterns and query performance issues
  • Supports configuration of autoscaling, scale-to-zero, and read replicas
  • Facilitates implementation of semantic, full-text, and hybrid search features
  • Assists with compute management tasks like resizing, suspending, and restarting

When to use it

  • When working with an existing DATABASE_URL, SQL, or database schema
  • When diagnosing high database bills or network egress issues
  • When planning isolated environments for migration testing or preview deployments
  • When implementing vector, full-text, or hybrid search capabilities
  • When needing to inspect database performance or compute behavior

Advantages

  • Provides clear distinctions between pooled and direct connection use cases
  • Offers structured workflows for database branching and migration testing
  • Includes specific diagnostic queries for identifying egress and performance bottlenecks
  • Integrates with Neon CLI and MCP for operational tasks
  • Supports modern development patterns like branch-per-PR

Usage examples

“How do I optimize my database egress costs?”
The agent will guide you through diagnosing top egress contributors using pg_stat_statements, analyzing your codebase for anti-patterns, and applying fixes like column selection and pagination.
“Create a new branch for testing my schema migration.”
The agent will verify your CLI or MCP authentication and execute the branch creation, providing you with the connection string for the new isolated environment.
“Which connection string should I use for my migration script?”
The agent will explain that migrations require a direct (unpooled) connection and help you identify the correct string without the -pooler suffix.
“How can I implement vector search in my Neon database?”
The agent will provide guidance on using Lakebase Search, including setting up the necessary extensions and managing the search implementation via your ORM.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/neondatabase/neon-postgres/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip neon-postgres.zip -d .agents/skills

Documentation by Neon

FIRST: Use the parent neon skill for a Neon overview, getting started with Neon, Neon development best practices, and more.

If the neon skill is not installed, fetch it from https://neon.com/docs/ai/skills/neon/SKILL.md or install it with:

neon skills -s neon -y

Lakebase Postgres

Lakebase Postgres is the database at the core of Neon. It runs on the lakebase architecture — OLTP built directly on cloud object storage — which decouples storage from compute to offer autoscaling, branching, instant restore, and scale-to-zero. It's fully compatible with Postgres and works with any language, framework, or ORM that supports Postgres.

It is the same database whether you reach it through Neon or through Databricks; this skill covers the Neon access path.

Login, users, sessions, and @neon/auth belong in neon-auth.

Live queries, reactive UIs, and realtime data belong in neon-realtime.

Setup Flow

1. Select the organization and project

If a DATABASE_URL is already supplied (prompt, environment, or repo) or a .neon file points at a project, use it. Do not list organizations or create a second project for schema work.

Otherwise use the CLI (default) or MCP server to list organizations and projects. Let the user select an existing project or create a new one.

2. Get the connection string

If a DATABASE_URL is already supplied, use it. Do not fetch another through the CLI or MCP.

Otherwise use the CLI (default), neon env pull, or the MCP server to get the connection string. Store it in .env as DATABASE_URL. Read the file first before modifying it, to avoid overwriting existing values.

When to use pooled vs direct connections
Use caseConnection type
Web applications, serverless functionsPooled (-pooler)
Schema migrationsDirect
pg_dump / pg_restoreDirect
Logical replicationDirect
Long-running analytics with temp tablesDirect
Admin tasks needing SET or session stateDirect
LISTEN / NOTIFYDirect
3. Pick the connection method and driver

Preserve the existing ORM and driver. For new TypeScript schema work with no established choice, Drizzle is a suggestion: https://neon.com/docs/guides/drizzle.md. Refer to the connection methods guide to pick the correct driver based on how the runtime treats your code: https://neon.com/docs/connect/choose-connection.md.

Driver notes:

  • On Vercel, use node-postgres (npm install pg) with Vercel Fluid compute and import { attachDatabasePool } from "@vercel/functions";

  • On Cloudflare, use node-postgres with Cloudflare Hyperdrive

  • On Neon Functions, use node-postgres, as the functions are long-running and reuse the pool across requests.

  • Use the @neondatabase/serverless driver for serverless and edge environments (for example, when using Netlify) — HTTP transport for one-shot queries, WebSocket for transaction support. Link: https://neon.com/docs/serverless/serverless-driver.md

4. Set up the schema

Manage schemas and migrations as code. Avoid running ad hoc schema migrations against your database, since they're hard to manage.

If you're using an ORM, follow your ORM's best practices to manage schemas and migrations. For example, if using Drizzle, only use Drizzle for schema and migration management unless instructed otherwise.

Branching

Use this when the user is planning isolated environments, schema migration testing, preview deployments, or branch lifecycle automation.

Key points:

  • Branches are instant, copy-on-write clones (no full data copy).

  • Each branch has its own compute endpoint.

  • Use the neon CLI or MCP server to create, inspect, and compare branches.

Link: https://neon.com/docs/introduction/branching.md

For detailed branch creation workflows (normal vs schema-only branches, reset-from-parent, CLI/MCP selection, and CI/CD patterns), read Branching workflows.

Migrations

Test a migration on a branch of production, against production-like data, before applying it to production.

Use a direct (non-pooled) connection string when you run the migration, not a pooled one. neon connection-string returns the direct string by default; make sure the hostname does not include the -pooler suffix.

Egress Optimization

Use this when a user reports high database bills, unexpected network transfer, egress spikes, query overfetching, or wants a cost-efficiency review of database query patterns.

Before editing code, read Egress optimization. Audit all five patterns: unused columns, missing pagination, repeated static reads, application-side aggregation, and JOIN duplication. Do not stop after fixing SELECT *.

Work in four steps: diagnose which queries transfer the most data, analyze the code behind them, fix the anti-patterns, then verify that behavior is preserved and transfer drops.

Troubleshooting and Neon-Specific Performance

Use Neon's predefined, read-only diagnostics before writing catalog queries by hand. The Neon CLI neon inspect db subcommands and the Neon MCP server's inspect_database tool run the same checks.

This section covers Neon-specific diagnostic tools, compute cache behavior, and platform signals. When the evidence points to generic Postgres work such as rewriting a query, choosing an index, changing a schema, or interpreting plan nodes, load the postgres-best-practices skill and carry the diagnostic evidence into that workflow.

Docs:

Choose CLI or MCP

Prefer the Neon CLI when terminal access and authentication are available:

neon inspect db <check>

The CLI resolves the project and branch from the current Neon context. Use --project-id, --branch, and --database-name to override it. Omit --database-name to inspect every database on the branch. Use --db-url only when inspecting a Postgres database directly instead of resolving it through the Neon API.

When using Neon MCP, call inspect_database with projectId and one check. Pass branchId, databaseName, or computeId only when needed. Omit databaseName to inspect all databases on the branch. Increase limit only when the result says it was truncated.

Pick the Diagnostic
Symptom or questionChecks
Which relations consume storage?table-sizes, index-sizes
Is an index unused or a table scanned heavily?unused-indexes, seq-scans
What has run for 5+ minutes or holds locks?long-running-queries, locks
Which queries consume the most total time?outliers
Which queries run most often?calls
Does the active data fit in compute cache?lfc-hit-rate, working-set
Is autovacuum behind or is space wasted?vacuum-stats, bloat
Is logical replication healthy?replication-slots, subscriptions

Do not confuse these checks:

  • long-running-queries reports statements running right now for more than five minutes.

  • outliers ranks the top queries by cumulative execution time since statistics were reset. It does not rank by mean latency.

  • calls ranks by execution count over the same statistics history.

outliers and calls require pg_stat_statements. lfc-hit-rate and working-set require the neon extension. If a check reports a missing extension, ask before running the suggested CREATE EXTENSION statement because installing an extension modifies the database.

Interpret Results Safely
  • Treat unused-indexes as a candidate list, not permission to drop indexes. Confirm the observation window, constraints, and workload before removal.

  • A sequential scan can be correct for a small table or a query reading much of a table. Check table size, selectivity, and the query plan before adding an index.

  • bloat is a statistical estimate. Confirm the impact and plan locks or maintenance before VACUUM FULL, REINDEX, or similar remediation.

  • Cache and Postgres statistics reset when compute restarts, including scale-to-zero suspension. Run a representative workload before interpreting fresh lfc-hit-rate, working-set, vacuum-stats, or pg_stat_statements results.

  • Compute-wide checks (lfc-hit-rate, working-set, and replication-slots) run once even when inspecting every database.

  • One failing database can fail an all-databases inspection; retry the relevant check with an explicit databaseName to isolate it.

Inspect Neon Cache Behavior Per Query

Standard EXPLAIN (ANALYZE, BUFFERS) reports Postgres shared-buffer activity, but it does not show Neon's Local File Cache (LFC) or page prefetching. For a safe read-only query, add Neon's FILECACHE and PREFETCH options:

EXPLAIN (ANALYZE, BUFFERS, PREFETCH, FILECACHE)
SELECT ...;
  • File cache: hits counts pages found in the compute's LFC.

  • File cache: misses counts pages not found in the LFC and fetched from database storage.

  • Prefetch: hits, misses, expired, and duplicates show how effectively Neon fetched pages before the executor requested them.

FILECACHE and PREFETCH provide metrics for this query and do not require the neon extension. By contrast, neon inspect db lfc-hit-rate and working-set provide compute-wide statistics and do require the extension.

The MCP explain_sql_statement tool can produce a standard plan but does not expose FILECACHE or PREFETCH options. To collect those Neon-specific metrics through MCP, use run_sql with the explicit, read-only EXPLAIN statement above.

Because ANALYZE executes the statement, use it only when execution is safe; do not run it autonomously for mutating SQL. Compare cold- and warm-cache runs carefully because the first execution can populate the cache and materially change later results.

Performance Workflow
  1. Reproduce the symptom and note its time window.

  2. Run the smallest relevant inspect checks from the table above.

  3. Identify a specific query before changing schema or compute. Use MCP explain_sql_statement for a standard plan, or the Neon-specific EXPLAIN above when LFC or prefetch behavior matters.

  4. If the bottleneck is query shape, indexing, schema, locking, or vacuum behavior, load postgres-best-practices and carry forward the inspection results and query plan. Keep Neon compute, cache, connection, and platform decisions in this skill.

  5. Re-run the same check and workload to verify the change.

Use MCP list_slow_queries instead of inspect_database when the user specifically needs queries ranked by average execution time with a custom threshold and limit. Outside the explicit EXPLAIN case above, use run_sql only for read-only diagnostic SQL when the predefined checks do not answer the question.

Computes

Use this when the user wants to resize a compute, change its scale-to-zero timeout, or start, suspend, restart, or delete it.

Manage computes with neon postgres computes. neon pg and neon lakebase are aliases of neon postgres.

neon postgres computes list                  # --branch <branch> or the branch .neon pins; --all-branches for the project
neon postgres computes get <compute-id>
neon postgres computes update <compute-id> --cu 0.25-2 --suspend-timeout 300
neon postgres computes restart <compute-id>  # also start, suspend, delete

update sends only the flags you pass (--cu, --suspend-timeout, --name, --disabled) and fails when you pass none. Each change waits until Neon applies it; update, start, suspend, and restart then print the compute. With --no-wait the command returns once the API accepts the change; find the operation with neon operations list and check it with neon operations get <operation-id>. Add a compute, such as a read replica, with neon branches add-compute <branch>.

Autoscaling

Use this when the user needs compute to scale automatically with workload and wants guidance on CU sizing and runtime behavior.

Set a compute's autoscaling range with neon postgres computes update <compute-id> --cu <min>-<max> (for example --cu 0.25-2), or a fixed size with --cu 2.

Link: https://neon.com/docs/introduction/autoscaling.md

Scale to Zero

Use this when optimizing idle costs and discussing suspend/resume behavior, including cold-start trade-offs.

Key points:

  • Idle computes suspend automatically after a default of 5 minutes. Change the timeout with neon postgres computes update <compute-id> --suspend-timeout <seconds>: 0 uses the plan default and -1 disables suspension. Free cannot change it, Launch can only enable or disable suspension, and Scale can set any value from 60 to 604800 (one week).

  • First query after suspend typically has a cold-start penalty (around hundreds of ms)

  • Storage remains active while compute is suspended.

Link: https://neon.com/docs/introduction/scale-to-zero.md

Keep hot reads off Postgres

Scale to zero only suspends an idle compute. When the same rarely changing rows (config, categories, feature flags) are read on every request, cache them outside Postgres, for example in Upstash Redis with a TTL. Cached reads cut egress and cold-start latency, and let an otherwise idle compute stay suspended.

Instant Restore

Use this when the user needs point-in-time recovery or wants to restore data state without traditional backup restore workflows.

Key points:

  • History windows for instant restore depend on plan limits.

  • Users can create branches from historical points-in-time.

  • Time Travel queries can be used for historical inspection workflows.

Link: https://neon.com/docs/introduction/branch-restore.md

Read Replicas

Use this for read-heavy workloads where the user needs dedicated read-only compute without duplicating storage.

Key points:

  • Replicas are read-only compute endpoints sharing the same storage.

  • Creation is fast and scaling is independent from primary compute.

  • Typical use cases: analytics, reporting, and read-heavy APIs.

Link: https://neon.com/docs/introduction/read-replicas.md

Connection Pooling

Use this when the user is in serverless or high-concurrency environments and needs safe, scalable Postgres connection management.

Key points:

  • Neon pooling uses PgBouncer.

  • Add -pooler to endpoint hostnames to use pooled connections.

  • Pooling is especially important in serverless runtimes with bursty concurrency.

Link: https://neon.com/docs/connect/connection-pooling.md

IP Allow Lists

Use this when the user needs to restrict database access by trusted networks, IPs, or CIDR ranges.

Link: https://neon.com/docs/introduction/ip-allow.md

Logical Replication

Use this when integrating CDC pipelines, external Postgres sync, or replication-based data movement.

Key points:

  • Neon supports native logical replication workflows.

  • Useful for replicating to/from external Postgres systems.

Link: https://neon.com/docs/guides/logical-replication-guide.md

Use Lakebase Search for semantic, full-text, and hybrid search:

Links:

Gotchas

Pooled vs direct connections: use the direct URL for migrations, dumps, and replication

Neon gives you two connection strings for the same database: a pooled one (hostname with the -pooler suffix) and a direct/unpooled one (no -pooler suffix). neon env pull writes them as DATABASE_URL and DATABASE_URL_UNPOOLED. The pooled connection routes through PgBouncer in transaction mode, which doesn't support session-level operations. Choose the right one:

  • Pooled (DATABASE_URL) — your application's normal query traffic, especially serverless and connection-per-request workloads.

  • Direct (DATABASE_URL_UNPOOLED) — schema migrations (Prisma Migrate, Drizzle Kit, Alembic, and others), pg_dump / pg_restore, logical replication, LISTEN/NOTIFY, and anything relying on SET or other session state.

Running migrations, dumps, or replication over the pooled connection can fail, and never in a way that names pooling: prepared statement "s0" already exists from Prisma Migrate, a SET search_path that doesn't persist past its own transaction so the next query reports relation "mytable" does not exist, or a write intermittently hitting a read-only transaction (SQLSTATE 25006) that a pooled backend inherited from an earlier client. Migration tools generally take both strings at once — Prisma's directUrl alongside url — so point that at the direct one rather than swapping DATABASE_URL and losing pooling for the application. See https://neon.com/docs/connect/connection-pooling.md.

Files

references/vector-search.md

Use lakebase_vector for approximate nearest-neighbor retrieval over embeddings. It retains pgvector's vector types, distance operators, and query syntax; the index access method is lakebase_ann.

Contents

  • Create the extension — enable lakebase_vector and its pgvector dependency

  • Prepare embeddings — generate vectors with the AI Gateway and match the column dimension

  • Build the index — match the distance metric, operator class, and query operator

  • Tune the index — configure index-build options and concurrent index management

  • Query — rank by vector distance or filter by a similarity radius

  • Tune search — inspect the index and tune recall against latency

    • Use prefilter selectively — apply selective filters before ANN scoring

Create the Extension

Lakebase Search requires Postgres 16 or later. Enable the extension before creating vector columns or indexes:

CREATE EXTENSION IF NOT EXISTS lakebase_vector CASCADE;

lakebase_vector installs pgvector through CASCADE. It relies on a preloaded library that Neon enables by default; if the project customized its preloaded-library list, confirm the library remains enabled.

Prepare Embeddings

Neon's AI Gateway embeddings endpoint is an OpenAI-compatible way to generate vectors for Lakebase Search. This table uses 1024 dimensions as an example; set the column dimension to the output of the model and any dimensions parameter you choose:

CREATE TABLE documents (
  id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  title text NOT NULL,
  body text NOT NULL,
  embedding vector(1024)
);

The AI Gateway is available on every Neon plan, including Free, and draws down prepaid AI Gateway credits. If a model shows enabled: false in GET /v1/models, the branch's AI Gateway page in the Neon Console lists the reason and the fix. See the neon-ai-gateway skill.

Enable the AI Gateway on the branch and get NEON_AI_GATEWAY_TOKEN and the bare-host NEON_AI_GATEWAY_BASE_URL:

  • With neon.ts, declare aiGateway: true, run neon deploy, then run neon env pull --file .env.

  • Without neon.ts, run neon env pull --service ai-gateway --file .env from a directory linked to the intended project and branch. This requests the gateway variables explicitly and skips other services.

  • Alternatively, get both values from the Neon Console. Neon Functions receive them automatically.

For TypeScript apps, use Neon's @neon/ai-sdk-provider 1.0.0+ with the Vercel AI SDK (ai, 6+) (npm install @neon/ai-sdk-provider ai dotenv). The provider reads NEON_AI_GATEWAY_TOKEN and NEON_AI_GATEWAY_BASE_URL directly and sends embedding requests to /v1/embeddings. Load .env in a standalone app; Neon Functions inject the variables automatically.

import "dotenv/config";
import { neon } from "@neon/ai-sdk-provider";
import { embed, embedMany } from "ai";

const embeddingModel = neon.embeddingModel("qwen3-embedding-0-6b");
const providerOptions = { neon: { dimensions: 1024 } };
// Qwen3 query prompt adapted for Neon documentation search; documents stay unprefixed.
const queryPrompt =
  "Instruct: Given a question about Neon, retrieve documentation passages that answer the question\nQuery: ";

const { embeddings: documentEmbeddings } = await embedMany({
  model: embeddingModel,
  values: documentBodies, // non-empty document batch; store vectors by input index
  providerOptions,
  maxParallelCalls: 1,
});
const { embedding: queryEmbedding } = await embed({
  model: embeddingModel,
  value: `${queryPrompt}${queryText}`,
  providerOptions,
}); // bind to $1 below

Skip empty imports before calling embedMany. It returns vectors in input order and splits requests according to the provider's item limit. For large imports, also split document text within the endpoint's token limits and keep database writes bounded.

For Neon documentation search, the example adapts the task instruction in Qwen3's stored query prompt from config_sentence_transformers.json. Its document prompt is empty, so document text stays unprefixed. Neither SDK applies SentenceTransformers prompts automatically. Keep the original queryText for BM25, and use the selected model's own prompt conventions if you switch models.

OpenAI SDK Alternative

For an existing OpenAI SDK integration, install openai and dotenv (npm install openai dotenv) and configure the client explicitly:

import "dotenv/config";
import OpenAI from "openai";

const apiKey = process.env.NEON_AI_GATEWAY_TOKEN;
const gatewayBaseUrl = process.env.NEON_AI_GATEWAY_BASE_URL;
if (!apiKey || !gatewayBaseUrl) {
  throw new Error("Missing Neon AI Gateway credentials");
}

const client = new OpenAI({
  apiKey,
  baseURL: `${gatewayBaseUrl}/v1`,
});

async function embedBatch(inputs: string[]): Promise<number[][]> {
  if (inputs.length === 0) return [];
  const response = await client.embeddings.create({
    model: "qwen3-embedding-0-6b",
    input: inputs,
    dimensions: 1024,
    encoding_format: "float",
  });
  const vectors: number[][] = [];
  for (const item of response.data) vectors[item.index] = item.embedding;
  return inputs.map((_, index) => {
    const embedding = vectors[index];
    if (!embedding) throw new Error(`Missing embedding for input ${index}`);
    return embedding;
  });
}

const documentEmbeddings = await embedBatch(documentBodies);
const [queryEmbedding] = await embedBatch([`${queryPrompt}${queryText}`]);
if (!queryEmbedding) throw new Error("Missing query embedding");

Use the same queryPrompt defined above, only for query inputs. Keep each batch within the endpoint's input and rate limits, and pair each vector with its source row using the response index. The OpenAI JavaScript SDK v6 defaults to requesting base64 and decodes the response as base64. If a compatible endpoint returns float arrays instead, that decoder can silently turn them into zeros. Pass encoding_format: "float" explicitly for the AI Gateway; the SDK then returns the float arrays directly. Base64 can reduce response size when an endpoint actually returns base64, but do not assume that format for this gateway.

Use the same model and output dimensions for stored documents and queries. Follow the model's input conventions: some models recommend a query instruction while document text remains unprefixed. If the model supports shorter vectors, compare retrieval quality, storage, and latency before changing dimensions; set the column and both embedding requests to the chosen size. Switching models requires re-embedding the corpus; changing dimensions also requires migrating the vector column and index. Generate embeddings in the application, outside SQL, unless the architecture already provides an in-database embedding function. Other embedding providers are also valid when their output matches the schema and index.

Build the Index

Choose the operator class and query operator as a matched pair:

MetricCommon useOperator classDistance operator
CosineMost text embeddingsvector_cosine_ops<=>
L2 / EuclideanAbsolute distance matters; vectors do not need normalizationvector_l2_ops<->
Inner productUnit-normalized vectors; matches cosine for unit vectorsvector_ip_ops<#>

Choose the metric recommended for the selected model, and keep its index operator class and query operator aligned. The Qwen3 Embedding model card demonstrates cosine similarity and normalized dot product for retrieval. For unit-normalized vectors, cosine, inner product, and L2 have the same exact ranking; approximate indexes can still differ in recall and latency, so benchmark on your corpus.

CREATE INDEX documents_embedding_ann ON documents
  USING lakebase_ann (embedding vector_cosine_ops);

Tune the Index

The default index options suit most workloads:

  • build_mode = 'standard' balances recall and index build time. Use quality for better recall when a longer build is acceptable.

  • lists = 'auto' chooses the IVF partition layout from the number of indexed vectors. Choose between auto and a manual value case by case: test both on the target dataset and use the value that better meets recall and performance targets.

To prioritize recall over index build time:

CREATE INDEX documents_embedding_ann_quality ON documents
  USING lakebase_ann (embedding vector_cosine_ops)
  WITH (build_mode = 'quality');

To override the automatic partition layout instead:

CREATE INDEX documents_embedding_ann_lists ON documents
  USING lakebase_ann (embedding vector_cosine_ops)
  WITH (lists = '1024');

For a large table, use CREATE INDEX CONCURRENTLY to avoid locking out writes while creating the index. For a frequently changing table, periodically use REINDEX INDEX CONCURRENTLY to rebuild the index with minimal write locking.

Query

Generate the query embedding with the same model and dimensions used for stored documents, following the model's query-input conventions (using the Qwen3 query prompt shown above), then bind it as a parameter:

SELECT id, title, embedding <=> $1::vector AS distance
FROM documents
ORDER BY distance
LIMIT $2;

Distance sorts ascending: a smaller value is a closer match. Keep the query operator consistent with the index operator class.

To filter by a similarity radius, use the matching boolean range operator in WHERE and the distance operator in ORDER BY:

SELECT id, title
FROM documents
WHERE embedding <<=>> sphere($1::vector, 0.5)
ORDER BY embedding <=> $1::vector
LIMIT $2;

The cosine range operator <<=>> returns a boolean; do not use it as the ranking expression.

Inspect the index before overriding defaults:

SELECT lakebase_ann_index_info('documents_embedding_ann');

This reports lists, default_probes, and default_epsilon. Small datasets use exact flat search before IVF lists are built. In that state, lists and default_probes are empty. Leave lakebase_ann.probes set to its default of 'auto'; lakebase_ann.epsilon still controls full-precision reranking during flat search.

For an IVF index, lakebase_ann.probes controls how many partitions are searched at each level. Higher values generally improve recall at the cost of speed. Its default is 'auto'. When lists is not empty, the shape of probes must match the shape of lists: use one value for a one-level index or two comma-separated values for a two-level index. At each level, the probes value must be no larger than the corresponding lists value. A mismatched or out-of-range value causes an error.

lakebase_ann.epsilon controls how many candidates are reranked using full-precision distances. Higher values rerank more candidates and take longer. Its default is 'auto', which works well for most workloads.

Use Prefilter Selectively

By default, PostgreSQL applies non-vector filters after the ANN index returns candidate rows. Enable prefilter when a filter is cheap to evaluate and removes most rows. Leave it off for loose or expensive filters.

BEGIN;
SET LOCAL lakebase_ann.prefilter = on;

SELECT id, title
FROM documents
WHERE id % 100 = 0
ORDER BY embedding <=> $1::vector
LIMIT $2;
COMMIT;

Start with probes and epsilon set to 'auto'. Benchmark manual probe values against representative query embeddings and choose the smallest values that satisfy recall and tail-latency targets. Keep session settings and the query in the same transaction when using a connection pool or stateless driver.

Source: lakebase_vector documentation.

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs an MCP server, Needs network access, Needs Node.js

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
Neon
Publisher
Neon (Official)
Source
neondatabase/agent-skills · skills/neon-postgres · commit 2b0e2b6
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced
Also distributed in
neondatabase/agent-skills

AutoGineer is not affiliated with or endorsed by Neon or Neon.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download neon-postgres.zip