Skip to main content
Make sure that ENABLE_BACKEND_ACCESS_CONTROL in your .env file is NOT set to False. Multi-user mode is enabled by default, therefore ENABLE_BACKEND_ACCESS_CONTROL=True by default.
The PGVector adapter is one of Cognee’s core vector adapters, along with LanceDB. Even though PGVector is an extension of Postgres, you can use PGVector as a vector store with other relational databases, such as SQLite.

Installation

Firstly, you will need to install specific dependencies necessary for working with Postgres and PGVector:

Setup

You will need a running Postgres database instance, and the existing handler works with both local and cloud setups. All you need to do is provide the necessary connection information, like the following example does for a local setup:
For the server setup, you can use the one from the Cognee docker-compose.yml file, or your own:

Usage

The PGVector handler is registered in Cognee by default, so all that is left to do is to let Cognee know which handler you are using. This can be done by setting the following .env variable:

Schema-per-dataset isolation (pgvector_shared)

The pgvector handler above gives every dataset its own Postgres database (CREATE DATABASE "<dataset_id>"). If you would rather keep everything in a single database, select the pgvector_shared handler instead:
In this mode each dataset’s vector collections live in a dedicated schema of Cognee’s existing relational database rather than in a separate database:
  • The schema name is derived automatically. Cognee names it ds_<dataset_id_hex> (the dataset UUID with hyphens stripped) and stores it in the dataset’s vector_database_connection_info. You do not supply a schema yourself.
  • Connection details come from the relational configuration. The host, port, database name, username, and password are taken from your DB_HOST / DB_PORT / DB_NAME / DB_USERNAME / DB_PASSWORD settings — not from the VECTOR_DB_* variables — because the shared database is Cognee’s relational database. Credentials are read from the live relational config at connection time and are never persisted in the dataset record.
  • Only CREATE SCHEMA privilege is required, not CREATE DATABASE.
  • Provisioning is automatic and idempotent. On first use Cognee runs CREATE EXTENSION IF NOT EXISTS vector and CREATE SCHEMA IF NOT EXISTS, so re-running add/cognify is safe and you do not need to create the schema or install the pgvector extension by hand.
  • Deleting a dataset drops its schema with a single DROP SCHEMA ... CASCADE, removing every table and index the dataset created.
Isolation is enforced by pinning the per-dataset PGVector engine’s search_path to "<dataset schema>, public". The dataset schema comes first, so reads and writes never fall through to public (which holds Cognee’s shared relational tables), while public stays on the path so the vector type remains resolvable. Table listing and deletion for these engines are likewise scoped to the dataset’s own schema. There is a matching graph handler, postgres_graph_shared, which isolates each dataset’s graph_node/graph_edge tables in the same way. See the list of supported handlers.
pgvector_shared requires VECTOR_DB_PROVIDER=pgvector. Selecting it with any other vector provider raises a ValueError when the dataset database is created.

Connection pool tuning

In multi-user mode each dataset gets its own PGVector engine, so the total number of open connections grows with the number of active datasets (number of datasets × pool size). To keep this fan-out in check, per-dataset PGVector engines fall back to a small connection pool (pool_size=2, max_overflow=20) when you have not sized the pool yourself. With the pgvector_shared handler every dataset engine points at the same database, so those pools all land on one connection target instead of fanning out across a separate database per dataset — but each dataset still has its own engine and its own pool, so the same sizing guidance applies. Pool arguments for these engines are resolved from the first source that is set:
  1. VECTOR_POOL_ARGS — explicit PGVector sizing, which always wins.
  2. The relational POOL_ARGS — inherited when VECTOR_POOL_ARGS is unset, so an operator who sized the pool explicitly outranks the built-in default.
  3. The built-in access-control default (pool_size=2, max_overflow=20) — used only when neither variable is set.
VECTOR_POOL_ARGS takes a JSON object whose keys are passed through to SQLAlchemy’s create_async_engine:
It applies only to PGVector per-dataset engines; leave it unset if you want these engines to follow POOL_ARGS instead. The value must be a JSON object; invalid JSON raises a configuration error (VECTOR_POOL_ARGS must be valid JSON) at startup. Restart your process or container after changing it so the new pool settings take effect.

SSL / connect args for managed Postgres

When a per-dataset PGVector engine connects to managed Postgres that enforces SSL (for example Neon), it now inherits the relational DATABASE_CONNECT_ARGS connection arguments, so asyncpg SSL options supplied there are honored for these engines too. Leaving DATABASE_CONNECT_ARGS unset is a no-op. See Relational Databases → Managed Postgres with SSL for the DATABASE_CONNECT_ARGS format.

Vector Stores

Details About Cognee’s Vector Stores

Multi-User Overview

More Details About Multi-User Mode