C.W.K.
Stream
Lesson 10 of 10 · published

Why PostgreSQL Wins by Being Good Enough at Everything

~12 min · extensions, philosophy

Level 0Schema Seedling
0 XP0/86 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

The architecture-shrinking pattern

Most teams reach for specialist databases because PostgreSQL looks general-purpose and therefore not best-in-class for any one job. The reality: PostgreSQL is best-in-class at most jobs — and the integration cost of running four specialist systems usually swamps the marginal performance gain of any one.

Where PostgreSQL is "good enough"

  • Document store: JSONB + GIN replaces MongoDB for almost all use cases.
  • Full-text search: tsvector + GIN replaces Elasticsearch for most use cases under a billion documents.
  • Vector search: pgvector + HNSW replaces dedicated vector DBs under ~10M vectors.
  • Geospatial: PostGIS is genuinely best-in-class — no compromise.
  • Time-series: TimescaleDB extension makes Postgres a strong time-series DB.
  • Cache layer: UNLOGGED tables + LISTEN/NOTIFY can replace Redis for many use cases.
  • Message queue: SKIP LOCKED job queues replace lightweight Celery/SQS for many use cases.

The honest exceptions

Genuine specialist tools win when you're past their scale point: petabyte analytics warehouses (BigQuery, Snowflake), sub-millisecond cache (Redis), millions of writes per second (Cassandra), real-time streams (Kafka). For everyone else: start with Postgres, add specialists when measured pain forces you to.

Code

One Postgres replacing four services·sql
-- 1. Document store (was MongoDB)
CREATE TABLE events (id BIGINT PRIMARY KEY, data JSONB);
CREATE INDEX events_data_gin ON events USING gin (data);

-- 2. Full-text search (was Elasticsearch)
ALTER TABLE articles ADD COLUMN tsv tsvector
GENERATED ALWAYS AS (to_tsvector('english', body)) STORED;
CREATE INDEX articles_tsv_gin ON articles USING gin (tsv);

-- 3. Vector search (was Pinecone)
CREATE EXTENSION vector;
ALTER TABLE documents ADD COLUMN embedding vector(1536);
CREATE INDEX documents_embedding_hnsw
ON documents USING hnsw (embedding vector_cosine_ops);

-- 4. Job queue (was Celery + Redis)
CREATE TABLE jobs (
    id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    payload JSONB NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending',
    created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- Worker pulls with: SELECT ... FOR UPDATE SKIP LOCKED LIMIT 1

External links

Exercise

List every external data store in your current architecture. For each, identify the PostgreSQL extension or feature that could replace it. Estimate the operational cost of each external service vs the marginal performance loss of switching.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.