---
title: "Is PostgreSQL Enough for Everything?"
description: "Before adding a separate search engine, queue, or document DB: how far PostgreSQL gets you on its own, and where its limit begins."
url: https://sade.dev/en/journal/is-postgresql-enough-for-everything/
lang: en
author: "Muhammet Şafak"
published: 2026-08-01
updated: 2026-09-06
section: Journal
tags: ["postgresql","database","architecture","opinion"]
summary: "Most of the list that puts Elasticsearch, MongoDB and RabbitMQ next to PostgreSQL is carried by a single PostgreSQL for a long time: tsvector with a GIN index for search, jsonb for documents, SELECT FOR UPDATE SKIP LOCKED for a moderate-volume queue. The limits are honest and real, but a second data system should arrive on a measured limit, not on a hunch or a blog post."
---

# Is PostgreSQL Enough for Everything?

> Most of the list that puts Elasticsearch, MongoDB and RabbitMQ next to PostgreSQL is carried by a single PostgreSQL for a long time: tsvector with a GIN index for search, jsonb for documents, SELECT FOR UPDATE SKIP LOCKED for a moderate-volume queue. The limits are honest and real, but a second data system should arrive on a measured limit, not on a hunch or a blog post.

An architecture plan, drawn up before there was a single user, carried this list: PostgreSQL for durable data, Elasticsearch for search, Redis for cache, MongoDB for flexible documents, RabbitMQ for queueing. Five separate data systems — each with its own backups, monitoring, version upgrades, and distinct failure mode.

Most of that list, for a long time, a single PostgreSQL carries on its own. The question isn't "can PostgreSQL do this"; it's "did you really buy the operational burden of these five systems".

## PostgreSQL's little-known breadth

Treating PostgreSQL as just a table-row store uses a small fraction of what it can do. Most of the needs that prompt a separate system are already inside it:

- **Full-text search.** A real search built on `tsvector`, `tsquery`, and a GIN index. It covers most apps' "search products" and "search posts" needs, including stemming, weighting, and ranking.
- **Document storage.** A `jsonb` column, paired with a GIN index, is a queryable document store. You can keep the fields that want schema flexibility right inside the relational table.
- **Queues.** `SELECT ... FOR UPDATE SKIP LOCKED` and `LISTEN/NOTIFY` run a moderate-volume job queue without a separate broker. Laravel's `database` queue driver uses the `SKIP LOCKED` half of it — its workers poll the jobs table at intervals rather than waiting on a `LISTEN/NOTIFY` signal.
- **Analytical queries.** Window functions, CTEs, materialized views — serious reporting without reaching for a separate analytical database.
- **Geospatial data.** Location queries via the PostGIS extension.

These features aren't "present but unused"; they're mature capabilities that run reliably in production.

## The quiet payoff of a single system

Every new data system isn't just a box; it's a maintenance commitment. What you gain by staying on one system:

- **One backup line.** One backup/restore procedure, one recovery drill.
- **One monitoring target.** One set of metrics to learn, one alerting setup to build.
- **Cross-consistency.** This is the most important one. If your search index lives in the same database as your data, there **can be no drift** between them — both update in the same transaction. A separate Elasticsearch will eventually fall out of sync with the data, and fixing that becomes its own line item.
- **One mental model.** The team learns the quirks of one system, not five.

This is the data-layer version of the innovation-token logic from the [boring architecture](/en/journal/why-boring-architecture) piece: every new system is a token, and tokens are limited.

## Where does the limit begin?

PostgreSQL isn't enough for everything — it has honest limits, and ignoring them is also a mistake:

- **Search.** When typo tolerance, advanced relevance tuning, faceted search, and multilingual analysis are needed at serious scale, a dedicated search engine genuinely pays off.
- **Queues.** When you need very high throughput, complex routing, or multi-consumer fan-out, a real message broker is the right tool. A PostgreSQL queue is comfortable at moderate volume, not at the extremes.
- **Write throughput.** Sustained writes beyond a single primary's fsync capacity — this is the hardest breaking point in [data-intensive systems](/en/systems/data-intensive-systems-breaking-points), and a real limit.

When you hit one of these limits, bringing in an extra system is the right call. Bringing it in before you hit it is just a guess.

## The decision: PostgreSQL first, then measure

The rule is plain: in a new project, make PostgreSQL do everything PostgreSQL can do. Let it be the first stop for search, queue, and cache-like needs. A separate system should arrive only when a **measured** limit is crossed — not from a hunch, a blog post, or résumé anxiety.

Most teams use maybe 20% of PostgreSQL, then say "it's not enough". What's not enough is usually not PostgreSQL, but the effort to get to know it.

---

PostgreSQL isn't enough for everything — but it's enough for far more than you think. Before you bring in a second data system, ask whether you've truly reached the end of the first.

PostgreSQL first; let the rest follow from measurement.

## Frequently asked

**Can PostgreSQL replace a separate search engine?**

For most applications, yes. tsvector, tsquery and a GIN index give a real full-text search with stemming, weighting and ranking. A dedicated engine starts paying off when typo tolerance, advanced relevance tuning, faceted search and multilingual analysis are needed at serious scale.

**Can PostgreSQL be used as a job queue?**

At moderate volume, yes. SELECT ... FOR UPDATE SKIP LOCKED lets several consumers pull work from a queue-like table without lock contention, and LISTEN/NOTIFY signals that the table changed. Very high throughput, complex routing or multi-consumer fan-out is where a real message broker is the right tool.


## Sources

- [Full Text Search: tsvector, tsquery, stemming and ranking](https://www.postgresql.org/docs/current/textsearch-intro.html) — PostgreSQL
- [JSON Types: jsonb and GIN indexing](https://www.postgresql.org/docs/current/datatype-json.html) — PostgreSQL
- [SELECT: the locking clause and SKIP LOCKED](https://www.postgresql.org/docs/current/sql-select.html) — PostgreSQL
- [NOTIFY](https://www.postgresql.org/docs/current/sql-notify.html) — PostgreSQL
