Module 7: Useful Extensions
Large extensions (mention): `pgcrypto`, `postgis`, `pgvector`
The extensions in capsules 03-06 are small/medium-scope — they cover a specific case. There are large extensions that deserve entire guides of their own: pgcrypto (auth/encryption), postgis (geospatial), pgvector (AI/embeddings). This capsule gives you awareness that they exist, what they solve, and when to redirect to their dedicated guide.
No deep dive — just so you know the ecosystem.
pgcrypto: auth and encryption
What it does: cryptographic functions inside PostgreSQL.
Typical cases:
- Hash passwords (
crypt(),gen_salt()). - HMAC for signing tokens.
- Encrypt/decrypt sensitive data.
- Random bytes (
gen_random_bytes()).
Example:
CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- Hash a password with bcrypt
SELECT crypt('mypassword', gen_salt('bf', 12));
-- $2a$12$JzLpY3HxJYO1pQqFaB...
-- Verify
SELECT crypt('mypassword', '$2a$12$JzLpY3HxJYO1pQqFaB...') = '$2a$12$JzLpY3HxJYO1pQqFaB...';
-- true
When to go deep: if your app needs auth with password hashing. But: in modern Python backends, hashing happens more in code (with argon2, bcrypt Python libs) than in the DB. pgcrypto stays relevant for specific cases.
Its own guide: Authentication & Authorization Guide (#9 of the Backend Python path). Goes deep on bcrypt vs argon2, JWT, OAuth2, RBAC.
Quick decision:
- App with simple auth in Python → Python libs (
passlib,argon2-cffi). - Auth logic in PostgreSQL stored procedures →
pgcrypto. - Encrypt-at-rest of specific columns →
pgcrypto.
postgis: geospatial data
What it does: full support for geographic information systems (GIS).
Typical cases:
- Store geographic points (lat/lng).
- "What's near my location" queries (radius search).
- Polygons (zones, coverage areas).
- Distance between points.
- Spatial indexing (GiST).
Example:
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE TABLE shops (
id SERIAL PRIMARY KEY,
name VARCHAR(200),
location GEOGRAPHY(POINT, 4326) -- WGS84 standard
);
INSERT INTO shops (name, location) VALUES
('Café Buenos Aires', ST_GeographyFromText('POINT(-58.3816 -34.6037)')),
('Café México DF', ST_GeographyFromText('POINT(-99.1332 19.4326)'));
-- Find shops within 5km of a point
SELECT name FROM shops
WHERE ST_DWithin(
location,
ST_GeographyFromText('POINT(-58.4 -34.6)'),
5000 -- meters
);
-- Calculate distance
SELECT name, ST_Distance(
location,
ST_GeographyFromText('POINT(-58.4 -34.6)')
) / 1000 AS distance_km FROM shops;
When to go deep: if your app handles maps, locations, "near me" queries.
Its own guide: doesn't exist in this path — it belongs to a dedicated geospatial data guide (future).
Quick decision:
- App with a "location" feature → seriously consider postgis.
- Just lat/lng as floats → may not need postgis (simpler but more limited queries).
Cloud: AWS RDS and Supabase have postgis. Check first.
pgvector: AI/embeddings
What it does: a vector type for storing embeddings and similarity search (cosine, L2, inner product).
Typical cases:
- Store text embeddings (OpenAI, Cohere, etc.) in PostgreSQL.
- Semantic search (find similar by meaning, not keyword).
- RAG (Retrieval-Augmented Generation) for LLMs.
- Recommendation systems with embeddings.
Example:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT,
embedding vector(1536) -- OpenAI ada-002 dimensions
);
-- Insert with an embedding (generated in Python via the OpenAI API)
INSERT INTO documents (content, embedding) VALUES
('PostgreSQL is great', '[0.1, 0.2, ...]'), -- 1536 floats
('Postgres is awesome', '[0.15, 0.25, ...]');
-- Find most similar (cosine distance)
SELECT content, embedding <=> '[0.12, 0.21, ...]' AS distance
FROM documents
ORDER BY embedding <=> '[0.12, 0.21, ...]'
LIMIT 5;
-- Index for fast search (HNSW or IVFFlat)
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);
When to go deep: if your app has AI features with embeddings (semantic search, RAG, similar items).
Its own guide: AI Engineering Path — Vector Databases Fundamentals (#7 of the AI path). Goes deep on pgvector vs Pinecone vs Weaviate vs ChromaDB, embeddings, indexing strategies.
Quick decision:
- App with simple RAG without too many vectors (<1M) → pgvector is excellent.
- Vectors >1M with high throughput → consider dedicated vector DBs (Pinecone, Weaviate).
- Team already uses PostgreSQL → pgvector is the path of least resistance.
Cloud: available in Supabase natively. AWS RDS has had it since 2024. Neon has it.
Other notable extensions (mention)
pg_partman
Advanced partitioning management. Auto-create partitions by time, retention policies. You already saw partitioning in module 4 — pg_partman is the extension that automates the housekeeping.
When: apps with tables that require recurring automatic partitioning (logs, events, time-series).
Cloud: AWS RDS has it but requires specific setup (it's not a simple extension).
pg_stat_statements
Tracking of the most expensive queries. You already saw it in guide #12 (Database Performance) module 5.
When: any app in production. Essential for performance debugging.
Cloud: available on all managed providers.
auto_explain
Auto-EXPLAIN for slow queries. Automatically logs the plans of queries that cross a threshold.
When: debugging slow queries in production. Complementary to pg_stat_statements.
pgaudit
Granular audit logging for compliance.
When: apps with regulatory requirements (HIPAA, SOC2, GDPR).
timescaledb
Optimized for time-series data. Auto-partitioning, compression, continuous aggregates.
When: events/metrics tables with billions of rows.
Cloud: Tigerdata Cloud, not in standard RDS.
cstore_fdw / Citus columnar
Columnar storage for analytics workloads. More compression, better aggregation queries.
When: data warehouse / analytics inside PostgreSQL.
pgmq
Message queue inside PostgreSQL. An alternative to Redis/RabbitMQ for simple queues.
When: a lightweight queue without adding a dependency. For complex queues, Redis/Kafka.
How to evaluate a new extension
When someone proposes using an extension you don't know:
1. Is it core or contrib?
- Core: part of official PostgreSQL. More stable.
- Contrib: additional extensions that ship with PG. Reliable.
- Third-party: community extensions. Check that they're maintained, popularity.
2. Official support from the cloud provider?
- Check the provider's docs (RDS, Supabase, Neon, etc.).
- If it's not supported, alternatives: switch provider or feature.
3. Is it maintained?
- GitHub stars, last commit, issues answered.
- Abandoned extension → risk. Avoid.
4. Alternatives in Python?
- If the extension does something you can do efficiently in Python code, use Python.
- Extension only if there's a clear benefit (performance, atomicity, simplicity).
5. Clear documentation?
- Tutorial, examples, troubleshooting.
- No docs → painful debugging.
Common traps with large extensions
1. Assuming it's available.
Each cloud provider maintains a whitelist. postgis for example is not on ALL providers. Check first.
2. Not accounting for overhead.
Large extensions (postgis, pgvector) have overhead in memory and disk. Don't add them "just in case".
3. Mixing extension versions between dev and prod.
pgvector 0.4 and pgvector 0.5 have different features. Sync them.
4. Forgetting licensing costs.
Some extensions (TimescaleDB community vs enterprise) have tiers. Check before assuming it's free.
5. Using an extension when a Python alternative exists.
If you have a Python library that does the same thing and performance doesn't matter, keep the stack simpler.
When to add a large extension vs an alternative
| Case | Consider first |
|---|---|
| Auth with passwords | Python passlib/argon2-cffi before pgcrypto |
| Maps/locations | If it's a core feature, postgis. If it's optional, simple lat/lng |
| AI search/RAG | pgvector if the app already uses PG. Dedicated vector DB if throughput >> 100k qps |
| Time-series | timescaledb if the dataset is >1B rows. Manual partitioning if smaller |
| Audit logging | Triggers + an audit table (module 3 of #13) if simple. pgaudit if strict compliance |
| Message queue | Redis/RabbitMQ if the app already has them. pgmq if you want simplicity |
Traps and common mistakes
1. Going deep on an extension you don't use.
Each large extension is a guide of its own. Going deep without a real need is time wasted. Knowing it exists is enough; go deep when you need to.
2. "Let's go with postgis just in case."
Setup, indexing, and maintenance of postgis are work. Only if you REALLY need geographic features.
3. Mixing pgvector + Pinecone "to scale."
Generally one or the other. Both together = sync complexity. Decide and stick with it.
4. Assuming an extension replaces good design.
pgvector doesn't fix bad data quality. pgcrypto doesn't fix bad auth design. Extensions expand capability — they don't replace thinking.
5. Adopting a trending extension without a real case.
pgvector is trending because of LLMs. If your app doesn't have real AI features, don't install it "to stay current".
Summary and next step
What you learned:
pgcrypto— auth/encryption. Belongs to the Auth Guide.postgis— geospatial. Its own geo guide (future).pgvector— AI/embeddings. Belongs to the AI Engineering path.- Other notable ones:
pg_partman,pgaudit,timescaledb,pgmq. - Evaluation: core/contrib/third-party, cloud support, maintained, Python alternatives.
- Traps: adopting without need, assuming availability, mixing tiers/versions.
In the next capsule we close the module with the mini-project: a refactor of a user system using 3 of the extensions we covered (citext, gen_random_uuid, pg_trgm). An integrated application of the decisions made in capsules 03-04-06.
Resources
- PostgreSQL — Extensions list — reference.
- PostGIS — official reference.
- pgvector — official repository.
- pgcrypto — reference.
- TimescaleDB — reference.
- pg_partman — repository.
- pgaudit — repository.
Capsule 07 of 08 — Module 7 — Advanced PostgreSQL for Backend Guide