Module A-15·23 min read

How Postgres extensions replace entire categories of specialized databases — without leaving ACID behind.

Module 15 — The Extensions Ecosystem: pg_cron, TimescaleDB, Citus, and pgvector

What this module covers: PostgreSQL's extension system is its most underappreciated feature. Extensions add capabilities that match or exceed dedicated NoSQL databases — without leaving the ACID guarantees, SQL interface, and operational tooling you already have. This module covers the four extensions that most frequently eliminate the need for a separate database: pg_cron for background job scheduling, TimescaleDB for time-series at scale, Citus for horizontal sharding, and pgvector for AI/embedding workloads.


Why Extensions Matter

In Module 11, we compared Postgres to MongoDB, Cassandra, and ClickHouse. Those comparisons assumed vanilla Postgres. With extensions, the picture changes:

  • Need time-series with columnar compression? → TimescaleDB makes Postgres competitive with InfluxDB and ClickHouse
  • Need horizontal write scaling? → Citus distributes Postgres across many nodes
  • Need vector similarity search for AI? → pgvector makes Postgres competitive with Pinecone and Weaviate
  • Need background job scheduling? → pg_cron replaces external cron + application-layer job tables

Each extension adds specialized capabilities while keeping the full Postgres stack: MVCC, WAL, ACID, SQL, pg_stat_*, your existing monitoring, your existing connection pooler, your existing backup tooling.


pg_cron: Background Job Scheduling Inside Postgres

pg_cron runs SQL or stored procedures on a cron schedule, directly inside the database process. No external scheduler, no separate worker service, no application-layer job table.

Installation and Setup

sql

Scheduling Jobs

sql

Managing Jobs

sql

When pg_cron Is the Right Tool

pg_cron is ideal for:

  • Database maintenance tasks (ANALYZE, VACUUM, partition creation)
  • Data retention cleanup (delete rows older than N days)
  • Periodic aggregation into summary tables
  • Refreshing materialized views on a schedule

It is not suitable for:

  • Long-running jobs that need external resources (API calls, file I/O)
  • Jobs that need distributed coordination across multiple Postgres instances
  • Jobs with complex dependency graphs (use Airflow, Prefect, or similar)

TimescaleDB: Time-Series at Postgres Scale

TimescaleDB is an open-source extension that adds automatic time-based partitioning (hypertables), columnar compression, and time-series-specific query functions on top of Postgres.

Hypertables

A hypertable is a Postgres table with automatic time-based partitioning managed by TimescaleDB. Data is partitioned into "chunks" automatically — no manual CREATE TABLE partition ... required.

sql

The hypertable looks and behaves like a regular Postgres table. All standard SQL works. TimescaleDB handles partitioning transparently.

Columnar Compression

TimescaleDB's native columnar compression is the feature that makes it genuinely competitive with InfluxDB and ClickHouse for time-series workloads.

sql

Typical compression ratios for time-series data: 10–40x. A 100GB raw metrics table becomes 3–10GB compressed. Compressed chunks are read using a columnar scan — only the requested columns are decompressed, dramatically reducing I/O for aggregation queries.

Continuous Aggregates

Continuous aggregates are materialized views that update automatically as new data arrives:

sql

Data Retention

sql

TimescaleDB vs Plain Postgres Partitioning

Plain Postgres PartitioningTimescaleDB
Partition creationManual or pg_partmanAutomatic
Columnar compressionNoYes (10–40x)
Continuous aggregatesManual with triggersNative
Retention policiesManual pg_cron jobNative
SQL compatibilityFullFull
Extension requiredNoYes

TimescaleDB is the right choice when: you have high-volume time-series data (metrics, events, IoT) that needs compression and fast aggregate queries, and you want to stay on Postgres rather than migrating to InfluxDB or ClickHouse.


Citus: Horizontal Sharding for Postgres

Citus distributes a Postgres database across multiple nodes — sharding both data and query execution. It is built by Microsoft and available as an open-source extension or managed service (Azure Cosmos DB for PostgreSQL).

The Citus Architecture

text

Distribution Key Selection

sql

The distribution key is the most critical decision. Choose it so:

  1. Frequently joined tables are colocated — if transactions and blocks are joined frequently, distribute both by a compatible key
  2. Hot queries filter on itWHERE sender = '0xabc...' goes to one shard, not all shards
  3. Data is evenly distributed — high-cardinality columns like UUIDs or blockchain addresses

Reference Tables

Some tables are small and frequently joined — distribute them to all workers:

sql

When Citus Is the Right Answer

Citus is appropriate when:

  • Write throughput exceeds what a single Postgres instance handles (~50,000+ TPS)
  • Data volume exceeds what a single server stores efficiently (10+ TB)
  • Most queries filter on the distribution key — if queries frequently scan all shards, sharding adds overhead without benefit

For most applications below these thresholds, a single Postgres primary with read replicas is simpler and sufficient.


pgvector: Vector Embeddings for AI Workloads

pgvector adds a vector data type and vector similarity search indexes to Postgres. It is the extension that makes Postgres competitive with dedicated vector databases like Pinecone, Weaviate, and Chroma for AI/RAG (Retrieval-Augmented Generation) workloads.

What Vector Search Is

An embedding is a fixed-size array of floating-point numbers that represents the semantic meaning of text, an image, or any other content. Embeddings with similar meaning have small vector distances. Searching for the most similar embeddings is the core operation in:

  • RAG (Retrieval-Augmented Generation): find documents semantically similar to a query, feed them to an LLM as context
  • Semantic search: return results by meaning, not keyword matching
  • Recommendation systems: find items similar to what a user engaged with
  • Duplicate detection: find near-duplicate content by vector proximity

Installation and Schema

sql

Inserting Embeddings

python

Vector Similarity Search: Exact vs Approximate

Exact search (no index — scans all vectors):

sql

Operators:

  • <-> — L2 (Euclidean) distance
  • <#> — negative inner product (for dot product similarity)
  • <=> — cosine distance (most common for text embeddings)

Exact search is O(N) — every vector is compared. For up to ~100K vectors, this is fast enough. Above that, you need an approximate nearest-neighbor (ANN) index.

IVFFlat Index

IVFFlat (Inverted File Flat) divides vectors into lists clusters. A query searches only the nearest N clusters instead of all vectors.

sql

Recall vs speed trade-off:

  • probes = 1: fastest, lowest recall (~70% of exact results)
  • probes = 10: balanced (~90% recall)
  • probes = lists: exact search (same as no index)

Build IVFFlat only after the table has data — the index quality depends on the data distribution at build time. Rebuild if data distribution changes significantly.

HNSW (Hierarchical Navigable Small World) builds a graph-based index with better recall/speed trade-offs than IVFFlat for most workloads.

sql

HNSW vs IVFFlat:

IVFFlatHNSW
Build timeFastSlower (especially for large datasets)
MemoryLowerHigher (graph stored in memory)
Recall at same speedLowerHigher
Incremental insertsRequires rebuild for best qualityGood — inserts update the graph
Best for>1M vectors, memory-constrainedMost workloads, especially with inserts

Hybrid Search: Vector + SQL Filters

The real power of pgvector in Postgres: combine semantic vector search with SQL predicates in one query:

sql

A dedicated vector database requires an additional filter step after the ANN search — often requiring you to fetch more candidates than needed and filter in the application. Postgres does this in a single query with the planner's cost model deciding the optimal execution order.

pgvector vs Dedicated Vector Databases

pgvectorPinecone / Weaviate
ACID transactionsYesNo
SQL filters in same queryNativePost-processing
Operational complexitySame as PostgresNew system to operate
Metadata storageJSONB + columnsSeparate metadata store
Scale~100M vectors (1536-dim, 128GB RAM)Unlimited (distributed)
CostPostgres hosting costPer-vector pricing

For most RAG and semantic search applications below 100M vectors: pgvector in Postgres eliminates the need for a dedicated vector database entirely. Your embeddings, metadata, and business data live in one system with consistent transactions.


Summary

ExtensionReplacesWhen to Use
pg_cronExternal cron + job tablesDB maintenance, data cleanup, periodic aggregation
TimescaleDBInfluxDB, ClickHouse (time-series)High-volume time-series, IoT metrics, automated compression
CitusManual sharding, Cassandra (write scale)>50K TPS write throughput or >10TB single-table datasets
pgvectorPinecone, Weaviate, ChromaRAG, semantic search, recommendation systems, <100M vectors

The principle: before adding a new database to your infrastructure, check if a Postgres extension solves the problem. The operational cost of one well-understood Postgres cluster is almost always lower than operating two specialized systems.


Knowledge Check

A software engineer needs to schedule a daily job that fetches data from an external REST API, processes it, and then inserts it into a PostgreSQL database. Considering the architectural design and limitations of pg_cron, which of the following statements is most accurate regarding its suitability for this task?


A team is building a RAG system with pgvector for a dataset of 50 million document embeddings (1536-dimensional). They anticipate frequent inserts and updates to the document collection, and require high recall for their semantic search queries, even at the cost of slightly slower query times. Which pgvector indexing strategy is most appropriate for this scenario?


A data engineering team is migrating a high-volume IoT sensor data pipeline to TimescaleDB. They've configured hypertables with 7-day chunk intervals and enabled columnar compression for chunks older than 30 days. They observe significant storage savings and are now optimizing dashboard queries that aggregate AVG(temperature) and MAX(humidity) over various time ranges. What is the primary performance benefit of TimescaleDB's columnar compression for these aggregation queries?

Test your knowledge with more question sets

Sign in to access a wider variety of questions and get notified when new practice sets are added to this module.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.