Skip to content
$EngineeringAtlas

The Case for Boring Databases

Postgres until you can prove you need something exotic.

Amit Kumar Singh2 min read

The Problem

Teams often add a specialized database before they have a specialized problem. That creates new backup, monitoring, access-control, migration, and operational work.

Why It Matters

Every datastore becomes an operational dependency. It needs backups, restore tests, schema ownership, dashboards, alerts, access controls, and incident knowledge. A small team can move faster by getting excellent at one database before adding more.

Postgres is boring in the best sense: it supports transactions, indexes, JSON, full-text search, extensions, replication, and years of operational knowledge.

Project Example

A SaaS app wants search, analytics, billing records, and admin dashboards. Start with Postgres tables, indexes, materialized views, JSONB where it is justified, and read replicas when needed. Add Elasticsearch, ClickHouse, or a vector database only when a measured workload proves Postgres is the bottleneck.

Implementation Example

Before adding a search cluster, try a generated tsvector column and a GIN index:

ALTER TABLE articles
ADD COLUMN search_text tsvector
GENERATED ALWAYS AS (
  to_tsvector('english', coalesce(title, '') || ' ' || coalesce(body, ''))
) STORED;

CREATE INDEX CONCURRENTLY idx_articles_search
ON articles USING gin (search_text);

This may be enough for internal tools, admin search, documentation search, and moderate SaaS workloads.

Implementation Checklist

  • Model transactions and constraints in Postgres first.
  • Add indexes based on EXPLAIN ANALYZE, not guesses.
  • Use migrations with rollback plans.
  • Track slow queries, lock waits, replication lag, and connection pool usage.
  • Keep backups and restore tests boring and automated.
  • Write down the access pattern before introducing a new datastore.
  • Calculate operational ownership, not only query speed.
  • Keep source-of-truth data in one place unless there is a strong reason.

When To Add Something Else

Use Redis when you need low-latency ephemeral state or caching. Use ClickHouse when analytical scans dominate. Use Elasticsearch or OpenSearch when rich search features matter. Use a vector store when ANN scale and metadata filtering outgrow Postgres.

Common Mistakes

  • Picking a database because a blog post made it look modern.
  • Moving data out of Postgres before defining consistency requirements.
  • Ignoring operational cost for small teams.
  • Treating JSONB as a replacement for schema design.
  • Adding eventual consistency before the product can explain it to users.

Summary

Boring databases let teams ship features while keeping operations understandable. Choose a new datastore only after the access pattern, scale, and failure model are clear.

Amit Kumar Singh

// written by

Amit Kumar Singh

Software engineer writing about backend systems, cloud, and the realities of running code in production.

$ subscribe --weekly

The weekly engineering digest

Production-grade engineering writing in your inbox. No spam, unsubscribe anytime.

## related