# Getting started with pgvector: from installation to your first vector search (Docker, Supabase, AWS RDS/Aurora, Neon, Cloud SQL, Azure)

> A getting-started guide to pgvector for beginning vector search in PostgreSQL. With real code faithful to the official documentation, it explains in the shortest path the enable procedure on each of Docker, Supabase, AWS RDS/Aurora, Neon, Google Cloud SQL/AlloyDB, and Azure, the permissions and common errors of `CREATE EXTENSION vector`, and your first table creation, INSERT, distance operators, kNN search, and HNSW index.

- Published: 2026-06-26
- Author: 友田 陽大
- Tags: PostgreSQL, RAG, Supabase, AWS, パフォーマンス
- URL: https://tomodahinata.com/en/blog/pgvector-getting-started-installation-docker-supabase-rds-neon-guide
- Category: Generative AI, LLMs & RAG
- Pillar guide: https://tomodahinata.com/en/blog/vercel-ai-sdk-production-llm-apps-streaming-tools-rag

## Key points

- The extension's name is `vector` (not the project name pgvector). On any platform, enabling it is the one line `CREATE EXTENSION vector;`.
- For Docker, the official image `pgvector/pgvector:pg17` is the shortest. For managed, RDS/Aurora, Neon, Cloud SQL, and Supabase support it; only Azure first needs allow-list registration in `azure.extensions`.
- 90% of stumbles are two: 'control file not found' = the binary isn't installed; 'permission denied' = insufficient privileges (rds_superuser / cloudsqlsuperuser / azure_pg_admin).
- The first search is the form `ORDER BY embedding <=> $1 LIMIT k`. For text embeddings, cosine distance `<=>` is the standard.
- There are 4 types: vector / halfvec / bit / sparsevec. Start with vector(dimensions), and add an HNSW index once it grows to millions of rows.

---

"I want to do vector search (semantic search) in PostgreSQL" — the entrance to that is **pgvector.** Without adding a dedicated vector DB, just add one `vector` type to the Postgres you already use, and you can store AI embedding vectors and search them "in order of closest meaning."

This article is a getting-started guide to take that **first step** — **enabling it on each platform** and **your first vector search** — in the shortest path. "The overall RAG design" and "index tuning" are left to other articles; this article guides you up to **"getting it running,"** faithful to the official documentation and crushing the stumble points.

> **Rules for this article**: extension names, SQL syntax, and each platform's enable procedure are based on the **pgvector official README and each cloud's official documentation (as of June 2026).** **A managed service's pgvector version is tied to the engine's minor and lags behind upstream.** Before use, always **check `pg_available_extensions` on your instance.** This article's versions and procedures may change.

---

## 1. Understand pgvector in 30 seconds

pgvector is a **PostgreSQL extension.** Enable it and the following three become usable.

1. **The `vector` type**: a column type to store embedding vectors (numeric arrays like `[0.1, -0.3, ...]`).
2. **Distance operators**: operators that measure "closeness" between vectors, such as `<=>` (cosine distance).
3. **ANN indexes**: HNSW / IVFFlat. Approximate-nearest-neighbor indexes that return neighbors fast even at millions of rows.

The most important caution first. **The extension's name is `vector` (not `pgvector`).** `pgvector` is the project name. When enabling in SQL, always write it like this on any platform.

```sql
CREATE EXTENSION vector;        -- ✅ 正しい（拡張名は vector）
-- CREATE EXTENSION pgvector;   -- ❌ これは存在しないのでエラーになる
```

---

## 2. Per platform: enable pgvector

"Run `CREATE EXTENSION vector;`" is common, but **its prerequisites (installing the binary / allow-list / permissions)** differ by platform. Reading only your environment's section is enough.

### Docker / self-host

The shortest is the **official Docker image.** The image name is `pgvector/pgvector`, and the tag is the form "Postgres major + Debian base" (e.g., `pg17`).

```bash
# 公式イメージ（pgvector がプリインストール済みの Postgres）
docker pull pgvector/pgvector:pg17
docker run -d --name pg -e POSTGRES_PASSWORD="$PGPASSWORD" -p 5432:5432 pgvector/pgvector:pg17
```

To install into existing Postgres from source (`pg_config` must be on PATH):

```bash
cd /tmp
git clone --branch v0.8.3 https://github.com/pgvector/pgvector.git
cd pgvector && make && sudo make install
```

It also installs via OS packages (`NN` is the Postgres major).

```bash
sudo apt install postgresql-17-pgvector     # Debian/Ubuntu（PGDG apt）
sudo dnf install pgvector_17                 # RHEL/Fedora（PGDG yum）
brew install pgvector                        # macOS
```

Finally, run once on the target database.

```sql
CREATE EXTENSION vector;
```

### Supabase

In the dashboard's **Database → Extensions**, search "vector" and turn the toggle ON, or run it in the SQL editor. By Supabase convention, put it in the `extensions` schema.

```sql
create extension vector with schema extensions;
```

### AWS RDS for PostgreSQL / Aurora PostgreSQL

pgvector is provided as a **trusted extension** of RDS / Aurora. The binary is already installed, so you just enable it.

```sql
-- まず使えるバージョンを確認（マネージドは本家より遅れることがある）
SELECT * FROM pg_available_extensions WHERE name = 'vector';

CREATE EXTENSION IF NOT EXISTS vector;
```

- **Permissions**: on PostgreSQL **13 or later**, if you have `CREATE` privilege on the database you can install a trusted extension even without being `rds_superuser` (12 or earlier needs `rds_superuser`).
- To use an **HNSW index**, pgvector **0.5.0 or later** is required. Older minors may not support it, so check with the `pg_available_extensions` above.

### Neon

Available on all plans. No extra configuration or special privilege needed.

```sql
CREATE EXTENSION IF NOT EXISTS vector;
-- 一つ前のバージョンに固定したいとき
-- CREATE EXTENSION vector VERSION '0.7.4';
```

### Google Cloud SQL for PostgreSQL / AlloyDB

Cloud SQL enables without flags. **It can be created by members of the `cloudsqlsuperuser` role** (the default `postgres` user holds it).

```sql
CREATE EXTENSION vector;                  -- 名前は vector（pgvector ではない）
```

**AlloyDB** can use, in addition to pgvector, Google's own **ScaNN** index. With `CASCADE`, `vector` is installed at the same time.

```sql
CREATE EXTENSION IF NOT EXISTS alloydb_scann CASCADE;  -- alloydb_scann + vector
```

### Azure Database for PostgreSQL — Flexible Server

Only Azure is **two-step.** **First register in the allow-list (`azure.extensions`)**, then `CREATE EXTENSION`. In the allow-list too, the name is `vector`.

```bash
# 1) サーバーパラメータ azure.extensions に VECTOR を許可（CLIの例）
az postgres flexible-server parameter set \
  --resource-group <rg> --server-name <server> \
  --name azure.extensions --value vector
```

```sql
-- 2) 対象DBで有効化（権限: azure_pg_admin）
CREATE EXTENSION vector;
```

### Quick reference: enable command and required privilege

| Platform | Prep | Enable | Required privilege |
| --- | --- | --- | --- |
| Docker / self-host | image or `make install` | `CREATE EXTENSION vector;` | superuser |
| Supabase | (preinstalled) | `create extension vector with schema extensions;` | (UI/SQL) |
| RDS / Aurora | (preinstalled, trusted) | `CREATE EXTENSION vector;` | `CREATE` on DB (PG13+) / `rds_superuser` (PG≤12) |
| Neon | none | `CREATE EXTENSION vector;` | no special privilege |
| Cloud SQL / AlloyDB | (preinstalled) | `CREATE EXTENSION vector;` | `cloudsqlsuperuser` |
| Azure Flexible Server | register in `azure.extensions` | `CREATE EXTENSION vector;` | `azure_pg_admin` |

---

## 3. Verification and common errors

Whether it enabled can be checked with the same SQL in any environment.

```sql
SELECT extversion FROM pg_extension WHERE extname = 'vector';   -- 入っていればバージョンが返る
SELECT * FROM pg_available_extensions WHERE name = 'vector';    -- 入れられるバージョン
```

In psql, list with `\dx` and details with `\dx vector`. Most stumbles are the following two. **Know the meaning and you can isolate them instantly.**

| Error | What it really means | Remedy |
| --- | --- | --- |
| `could not open extension control file ".../vector.control": No such file or directory` | **the binary isn't installed** (not a permission problem) | use `make install` / the package for the correct PG major / a Docker image with pgvector |
| `permission denied to create extension "vector"` | **insufficient role privilege** | grant superuser / `rds_superuser` / `cloudsqlsuperuser` / `azure_pg_admin`, or `CREATE` privilege on the DB |
| `extension "vector" is not allow-listed for "azure.extensions" setting` | on Azure, **not registered in the allow-list** | add `vector` to `azure.extensions` and rerun |

---

## 4. Your first vector search

Once enabled, finally the search. Go through the minimal flow of **create table → insert → kNN search.**

```sql
-- 1) 埋め込みを格納するテーブル。vector(3) の 3 は次元数（実際は埋め込みモデルの出力次元に合わせる）
CREATE TABLE items (
    id        bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    content   text NOT NULL,
    embedding vector(3) NOT NULL
);

-- 2) 投入。ベクトルは '[...]' のテキストリテラルで渡す
INSERT INTO items (content, embedding) VALUES
    ('りんご', '[1, 2, 3]'),
    ('みかん', '[1, 2, 4]'),
    ('自動車', '[9, 8, 1]');

-- 3) クエリベクトルに「意味が近い順」で上位2件（kNN検索）
SELECT id, content, embedding <=> '[1, 2, 3]' AS distance
FROM items
ORDER BY embedding <=> '[1, 2, 3]'   -- 小さいほど近い
LIMIT 2;
```

### Distance operators: choose by use

How to measure vector "closeness" is chosen by operator. The iron rule is to **match the distance the embedding model assumes.**

| Operator | Distance | Main use |
| --- | --- | --- |
| `<=>` | cosine distance | **the standard for text embeddings** (measures meaning by direction) |
| `<->` | L2 (Euclidean) distance | general unnormalized vectors |
| `<#>` | negative inner product | inner-product-based models |
| `<+>` | L1 (Manhattan) distance | L1 space |
| `<~>` / `<%>` | Hamming / Jaccard distance | `bit` type (binary vectors) |

For text embeddings like OpenAI's `text-embedding-3-*`, choosing **`<=>` (cosine distance)** first is foolproof.

> **What about real data?**: the `'[1,2,3]'` above is a hand-written vector for explanation. In reality you `INSERT` a several-hundred-to-thousand-dimensional vector obtained by passing text to an embedding model (OpenAI, Cohere, your own model, etc.). How to pass it from the app side is handled in detail in the [type-safe implementation with TypeScript × Drizzle](/blog/pgvector-typescript-drizzle-orm-nextjs-type-safe-vector-search-guide).

---

## 5. The four vector types and the dimension cap

pgvector has four types by use. **Start with `vector` and consider others when needed** is enough (YAGNI).

| Type | Size per element | Indexable dimensions | Where to use |
| --- | --- | --- | --- |
| `vector(n)` | 4 bytes (float32) | up to **2,000** | **standard. this first** |
| `halfvec(n)` | 2 bytes (float16) | up to **4,000** | half the memory, high dimensions |
| `bit(n)` | 1 bit | up to **64,000** | binary quantization (Hamming distance) |
| `sparsevec(n)` | stores only non-zero | up to **16,000** non-zero | sparse representation (SPLADE, etc.) |

The `n` of `vector(n)` must **match the embedding model's output dimensions** (a mismatch is a dimension-mismatch error on `INSERT` = the benefit of being protected by the type). OpenAI's `text-embedding-3-large` is 3072 dimensions, but it can be shortened with the `dimensions` parameter, and in my projects I operate at 1024 dimensions (the reason is detailed in the [RAG-design article](/blog/pgvector-postgres-production-rag-hybrid-search)).

---

## 6. Your first index (HNSW)

For a few rows, a full scan is enough, but **at millions of rows the full scan every time breaks down.** So add an approximate-nearest-neighbor (ANN) index. When in doubt, **HNSW** (strong for continuous additions and can be created in advance on an empty table).

```sql
-- コサイン距離で検索するなら vector_cosine_ops（距離演算子と演算子クラスを必ず揃える）
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);

-- 検索精度↔速度は、インデックス再構築なしでランタイムに調整できる
SET hnsw.ef_search = 100;   -- 既定40。大きいほど高再現率・低速
```

Whether the index is working is confirmed with `EXPLAIN` (OK if `Index Scan using ..._hnsw_...` appears).

```sql
EXPLAIN ANALYZE
SELECT id FROM items ORDER BY embedding <=> '[1,2,3]' LIMIT 5;
```

> **Important**: the index works only for the form "`ORDER BY embedding <operator> ... LIMIT k`." The meaning of parameters like `m` / `ef_construction` / `ef_search`, how to choose between HNSW and IVFFlat, and how to measure recall are systematized in the dedicated article [the complete pgvector tuning guide](/blog/pgvector-index-tuning-hnsw-ivfflat-quantization-iterative-scan-guide).

---

## 7. Articles to read next (from here to production)

After "it ran," digging in this order by purpose is the shortest.

- **Want to build RAG (AI answers from internal docs)** → [building production RAG with pgvector](/blog/pgvector-postgres-production-rag-hybrid-search) (where to put embeddings, hybrid search, idempotent ingest)
- **Search is slow / accuracy isn't there** → [the complete pgvector tuning guide](/blog/pgvector-index-tuning-hnsw-ivfflat-quantization-iterative-scan-guide) (HNSW/IVFFlat, quantization, measuring recall)
- **Torn over a dedicated vector DB** → [pgvector vs. Pinecone/Qdrant/Weaviate/Milvus selection](/blog/pgvector-vs-pinecone-qdrant-weaviate-milvus-vector-database-comparison-guide)
- **Want a type-safe implementation in TypeScript / Next.js** → [pgvector × Drizzle ORM × Next.js](/blog/pgvector-typescript-drizzle-orm-nextjs-type-safe-vector-search-guide)

---

## Conclusion: the shortest checklist

- **The extension name is `vector`.** Enabling is the one line `CREATE EXTENSION vector;` in any environment.
- **The platform difference is only the "prerequisite"**: for Docker, the official image `pgvector/pgvector:pg17`; only Azure needs `azure.extensions` permission first. Check the managed version with `pg_available_extensions`.
- **Errors are two lines**: `control file not found` = binary not installed; `permission denied` = insufficient privilege.
- **The first search**: a `vector(n)` column → `INSERT '[...]'` → `ORDER BY embedding <=> $1 LIMIT k`. Text uses `<=>`.
- **Add HNSW once it scales**: `USING hnsw (embedding vector_cosine_ops)`, tune accuracy with `hnsw.ef_search`.

The goodness of pgvector is that you can begin vector search **inside the PostgreSQL you already use, with the SQL, permissions, and backups you're used to.** In the [generative-AI voice chatbot](/case-studies/ai-voice-chatbot), I consolidated business data and embeddings into pgvector on RDS without adding a dedicated vector DB, and carried production RAG through design, implementation, and operation with one person × generative AI (Claude Code).

**"I want to start AI semantic search on my own company's data but don't know where and how to host it" — I can accompany you end-to-end from that entrance through production operation.** Feel free to reach out.

---

### References (official documentation)

- [pgvector (GitHub, README)](https://github.com/pgvector/pgvector) — installation (Docker / source / OS package), `CREATE EXTENSION vector`, types and distance operators, HNSW / IVFFlat
- [Supabase — pgvector](https://supabase.com/docs/guides/database/extensions/pgvector) / [AWS RDS extensions](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Extensions.html) / [Neon — pgvector](https://neon.com/docs/extensions/pgvector) / [Google Cloud SQL extensions](https://cloud.google.com/sql/docs/postgres/extensions) / [use pgvector on Azure Flexible Server](https://learn.microsoft.com/azure/postgresql/extensions/how-to-use-pgvector)
