Audience: Anyone building data harnesses on Postgres — quant researchers,
experimental scientists, knowledge engineers, platform builders.
Goal: Understand what each extension does in one line — and which problem it solves in your domain.
You do not need a separate vector DB, graph DB, and time-series DB if Postgres + extensions fit your scale. This guide helps you choose.
13 + built-in FTS
vector · age · pg_trgm
one Postgres hub
Section 00
How to read this doc
Section
Purpose
TLDR table
Pick extensions in 60 seconds
Per-extension
Definition → when to use → examples by field
Head-to-head
AGE vs Neo4j, pgvector vs Pinecone, and more
Decision matrix
"I need X" → extension Y
Harness patterns
Four extension stacks — read left to right
Install order
Safe rollout on research or prod server
Built-in (no extension): PostgreSQL already includes full-text search (to_tsvector, tsquery), JSONB, Arrays and window functions. Many projects never need more than that.
Section 01
TLDR
Extension
TLDR (one line)
Typical domains
vector
Store vectors; find nearest neighbors by cosine/L2 distance
ML embeddings, semantic search, compound similarity
Entity names, tickers, chemical synonyms, log grep
btree_gin
Efficient GIN indexes on JSONB and composite keys
Metadata filters, experiment parameters in JSON
pg_stat_statements
Profile SQL: which queries cost the most time
Production, heavy notebook-driven workloads
pg_cron
Schedule SQL inside the database
Nightly ETL, rollups, model refresh, cleanup
ltree
Tree paths as a native type (a.b.c.d)
Taxonomies, BOMs, org charts, folder hierarchies
citext
Case-insensitive text columns
Symbols, gene names, user handles
timescaledb
Time-series hypertables, retention, compression
Market ticks, sensor streams, lab instrument logs
rum / pg_bm25
Better-ranked full-text search than default ts_rank
Literature search, document corpora
hypopg
Test hypothetical indexes (EXPLAIN only)
Index tuning before migration
pg_repack
Online table rewrite to remove bloat
Long-running append/update tables
postgis
Geometry and spatial predicates (points, polygons)
GIS, microscopy coordinates, field sites
Section 02
The harness-building idea
A data harness is a stable layer between raw inputs (files, APIs, instruments) and your analysis (Python, R, notebooks, dashboards). Postgres is often enough as the hub.
Why extensions instead of many databases? One backup, one connection model, joins between embeddings and metadata, transactional consistency. Trade-off: you must know which extension fits which shape of data.
Section 03
Tier 1 — high leverage
vector (pgvector)
TLDR: Adds a vector column type and distance operators for approximate nearest neighbor (ANN) search over embeddings.
Vectors in the same table as labels, timestamps, and JSON metadata.
When not to use
Billion-scale ANN with strict sub-10ms SLA — you may later shard or add a dedicated vector service. For thousands to low millions of rows, pgvector is often sufficient.
Domain
Example use
Quant / ML
Embed research notes or news headlines; retrieve context for factor models
Physics
Similarity over reduced simulation state vectors; cluster regimes
Chemistry
Molecular fingerprints (ECFP, etc.) stored as vectors; nearest analogs
Knowledge systems
Semantic search over archival text chunks (embedding + content in one row)
CREATE EXTENSION vector;
CREATE TABLE compounds (
id serial PRIMARY KEY,
smiles text,
fingerprint vector(2048)
);
SELECT id, smiles, fingerprint <=> $1 AS distance
FROM compounds
ORDER BY distance
LIMIT 20;
age (Apache AGE)
TLDR: Adds a labeled property graph and openCypher inside PostgreSQL — graph pattern matching without a separate Neo4j server.
When to use
Relationships are as important as entities (who traded with whom, what cites what, what reacts with what).
Multi-hop queries: “friends of friends”, “supply chain depth 3”, “path from concept A to B”.
Graph + SQL joins in one transaction.
When not to use
Pure trees (use ltree or adjacency list). Massive graph analytics at internet scale with dedicated ops team — consider a dedicated graph engine.
graph LR
M1(("Molecule A"))
R(("Reaction"))
M2(("Molecule B"))
M1 -->|REACTS_IN| R -->|PRODUCES| M2
CREATE EXTENSION age;
LOAD 'age';
SELECT * FROM cypher('science_graph', $$
MATCH (a:Molecule {name: 'benzene'})-[:REACTS_IN*1..3]-(b:Molecule)
RETURN DISTINCT b.name
$$) AS (name agtype);
Note: AGE implements a subset of openCypher. Complex graph algorithms (PageRank at huge scale) may still belong in batch frameworks — but traversal and pattern match often belong here.
pg_trgm
TLDR:Trigram similarity — match strings that are almost equal (typos, formatting differences).
When to use
User-facing search over names, symbols, or labels with inconsistent spelling.
Deduplication: “are these two instrument IDs the same?”
Joining messy external data to a clean registry.
Domain
Example use
Quant Finance
BRK.A, BRK-A, Berkshire in a corporate-action lookup
Physics
Fuzzy match on experiment IDs or collaborator names in lab notebooks
Chemistry
Synonym resolution: acetone vs. propan-2-one in imported catalogs
Knowledge Systems
Tag search when users type redroom vs. red-room type
CREATE EXTENSION pg_trgm;
SELECT name, similarity(name, 'Hilbert space') AS sim
FROM papers
WHERE name % 'Hilbert space'
ORDER BY sim DESC
LIMIT 10;
Pitfall: Short tokens (nic, ion) can false-positive inside longer words — use word boundaries or minimum similarity thresholds in production.
btree_gin
TLDR: Enables GIN index patterns that combine equality and containment — especially powerful for JSONB keys and multi-column GIN.
When to use
Heavy filtering on metadata->>'parameter' or nested JSON experiment configs.
You run WHERE properties @> '{"solvent": "water"}' at scale.
Domain
Example use
Quant
Filter backtest runs by strategy params in JSONB
Physics
Query simulations by lattice size, boundary condition in metadata
Chemistry
Filter reactions by catalyst family in JSON protocol blob
Knowledge
Filter records by source, person_id, scores in JSON
CREATE EXTENSION btree_gin;
CREATE INDEX ON runs USING gin ((config->'solver'));
Section 04
Tier 2 — operations, time, and structure
pg_stat_statements
TLDR: Records aggregate stats per normalized SQL statement — the standard way to find slow queries.
When to use: Any database that matters — notebook-driven chaos eventually becomes someone’s 3am incident.
CREATE EXTENSION pg_stat_statements;
SELECT query, calls, mean_exec_time, total_exec_time
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 15;
pg_cron
TLDR: Cron-style job scheduler that runs SQL inside Postgres.
Tier 3 — search quality, tuning, maintenance, space
Built-in full-text search (tsvector / tsquery)
TLDR: Keyword search with tokenization and ranking — no extension required.
When to use: Document bodies, abstracts, log messages — exact and stemmed word match, not embedding similarity.
Domain
Example
Quant
Search research PDF extract for “carry trade”
Physics
Grep paper corpus for “renormalization”
Chemistry
Find procedures mentioning “Grignard”
CREATE INDEX ON papers USING gin (to_tsvector('english', abstract));
SELECT title FROM papers
WHERE to_tsvector('english', abstract) @@ plainto_tsquery('english', 'topological insulator');
rum / pg_bm25
TLDR: Full-text indexes with BM25-style relevance — often better ranking than ts_rank_cd.
When to use: Large corpora where keyword relevance quality matters (literature, regulations, patents).
hypopg
TLDR:Hypothetical indexes — planner considers them in EXPLAIN without building them.
When to use: Before adding heavy indexes on production tables; compare plan cost estimates.
pg_repack
TLDR: Rebuilds tables online to reclaim space from update/delete bloat.
When to use: Append-heavy or churn-heavy tables (event logs, archival stores) when VACUUM is not enough.
postgis
TLDR:Spatial types and predicates — distance, containment, intersections on Earth or projected CRS.
When to use: Field sampling sites, microscopy stage coordinates, geographic portfolios.
Domain
Example
Quant
Branch/store locations for regional risk
Physics / Earth science
Sensor geolocation; field campaign sites
Chemistry
Less common — unless environmental sampling maps
CREATE EXTENSION postgis;
SELECT id FROM sites
WHERE ST_DWithin(geom, ST_MakePoint(-73.98, 40.75)::geography, 5000);
Section 06
Head-to-head comparisons
When does a Postgres extension beat a dedicated service — and when does the dedicated tool still win?
Graph
Apache AGE vs Neo4j
Dimension
AGE + Postgres
Neo4j
Architecture
Graph inside your existing DB
Separate graph server + sync
SQL joins
Native — episodes + metadata in one query
Requires ETL or app-layer merge
Cypher
openCypher subset
Full Cypher + graph algos
Ops
One backup, one connection pool
Two systems to monitor
Scale
Research / platform scale (millions of edges)
Internet-scale graph analytics
Pick AGE when
Graph traversal + relational truth in one transaction; no Neo4j ops budget
Pick Neo4j when
Dedicated graph team, heavy GDS algorithms, strict graph-only SLA
Vectors
pgvector vs Pinecone / Qdrant
Dimension
pgvector
Dedicated vector DB
Data model
Vectors + JSON metadata in same row
Vectors often separate from source of truth
Filtering
SQL + GIN on metadata alongside ANN
Metadata filters vary by vendor
Latency at huge scale
Good to ~low millions; shard later
Sub-10ms at billions with HNSW tiers
Cost
Postgres you already run
Extra SaaS or cluster
Pick pgvector when
Embeddings live with archival rows; hybrid semantic + SQL filters
Pick dedicated when
Global ANN at billions, strict latency SLA, separate vector team
Time series
TimescaleDB vs InfluxDB
Dimension
TimescaleDB
InfluxDB
Query language
SQL — joins with relational data
InfluxQL / Flux
Hypertables
Auto partition + retention in Postgres
Built for metrics from day one
Ecosystem
Same ORMs, same backups as Postgres
Separate ingest + tooling
Pick Timescale when
Ticks/bars/sensors must join to reference tables in SQL
Pick Influx when
Pure metrics pipeline, no relational joins needed
Search
Postgres FTS vs Elasticsearch
Dimension
Postgres FTS (+ rum)
Elasticsearch
Setup
Built-in; rum/pg_bm25 for better rank
Separate cluster + sync pipeline
Strength
Keyword + metadata in one DB
Full-text at massive doc scale, analyzers
Pick Postgres when
Corpus fits in Postgres; hybrid keyword + vector + graph
Pick Elasticsearch when
Huge document index, complex analyzers, search-only team
Spatial
PostGIS vs MongoDB Geo
Dimension
PostGIS
MongoDB GeoJSON
Data model
Geometry types + SQL joins to relational rows
GeoJSON documents in a document store
Standards
OGC predicates, CRS, topology, raster
2dsphere indexes; simpler geo queries
Strength
Field sites + lab metadata + vectors in one query
Fast geo-in-document apps without SQL
Pick PostGIS when
Spatial filters must join experiments, portfolios, or samples in SQL
Pick Mongo when
Document-first app; geo is a filter on JSON blobs only
Section 07
Decision matrix
You need…
Start here
Also consider
Similarity on embeddings
vector
—
“Related items” by meaning + filters
vector + btree_gin on metadata
—
Multi-hop relationships
age
ltree if strict tree only
Typo-tolerant name/symbol search
pg_trgm
citext for equality
Time-range aggregates at scale
timescaledb
native partitioning
Keyword search in documents
Built-in FTS
rum if ranking weak
Map / distance queries
postgis
—
Slow query diagnosis
pg_stat_statements
—
Scheduled SQL maintenance
pg_cron
external orchestrator
Index tuning without risk
hypopg
—
Section 08
Harness patterns
Four ready-made extension stacks. Each row is one layer in the harness — read left to right, then the hub line shows what you get.
A → B → C extension layers in order→ hub combined outcome / API surfaceanimated arrows data flows left to right
A
Semantic lab notebook
Scientists write notes; you need meaning search, fuzzy IDs, and JSON experiment filters — without three databases.
vectorembed note paragraphs
→
pg_trgmfuzzy sample IDs
→
FTSkeyword fallback
→
JSONB+ginexperiment params
→ unified lab search API
B
Market + exposure graph
Time-series bars, counterparty relationships, and news context — one harness for quant risk.
timescaledbbars & ticks
→
agecounterparty graph
→
vectornews embeddings
→
pg_stat_statementstune hot paths
→ exposure + context dashboard
C
Chemical intelligence
Fingerprint similarity, reaction networks, and site sampling — chemistry R&D in one Postgres hub.
vectorfingerprint similarity
→
agereaction network
→
postgissite sampling
→
pg_trgmsynonym matching
→ compound discovery pipeline
D
Episodic knowledge archive
Long-horizon agent memory: semantic recall, people/doc graph, fast API reads — no Postgres + Neo4j + vector SaaS.
vectorsemantic recall
→
ageepisode graph
→
pg_trgmfuzzy tags
→
edges tablematerialized + gin
→ relational truth + materialized links + optional Cypher
All patterns · one database hub
flowchart TB
subgraph PA["A · Lab notebook"]
direction LR
v1[vector] --> h1[(search)]
t1[trgm] --> h1
end
subgraph PB["B · Market graph"]
direction LR
ts2[timescale] --> h2[(risk)]
a2[age] --> h2
end
subgraph PC["C · Chemistry"]
direction LR
v3[vector] --> h3[(discovery)]
g3[postgis] --> h3
end
subgraph PD["D · Knowledge"]
direction LR
v4[vector] --> h4[(memory)]
a4[age] --> h4
end
PG[(PostgreSQL hub)]
PA --> PG
PB --> PG
PC --> PG
PD --> PG
Section 09
Suggested install order
Any serious Postgres harness — core first, domain-specific when needed.
-- Core analytics
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS btree_gin;
-- Observability
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- Domain-specific (add when needed)
CREATE EXTENSION IF NOT EXISTS age; -- graphs
CREATE EXTENSION IF NOT EXISTS timescaledb; -- time series
CREATE EXTENSION IF NOT EXISTS postgis; -- spatial
CREATE EXTENSION IF NOT EXISTS pg_cron; -- schedules (policy!)
Match extension packages to your Postgres major version (e.g. postgresql-16-pgvector).
Section 10
What extensions do not replace
Need
Extension helps but…
Training neural nets
Store vectors; train in Python/Julia
Heavy graph ML (GNN training)
Export subgraphs to PyG/DGL
Sub-millisecond global ANN at billions
Dedicated vector tier may be needed
Full document OCR
Store text after extraction
Real-time stream processing at Kafka scale
Ingest via stream processor; Postgres as sink
Section 11
Security checklist
Treat pg_cron and age as privileged capabilities on shared servers.
Do not expose arbitrary Cypher/SQL endpoints to untrusted users without allowlists.
Extension install often requires superuser — document who can change shared_preload_libraries.
Fuzzy matchers (pg_trgm) can leak existence of similar strings — tune thresholds on sensitive data.