HN Debrief

PostgreSQL is enough (2024)

  • Infrastructure
  • Databases
  • Startups
  • Developer Tools

The gist is a catalog of things people often reach for separate systems to handle, then asks whether PostgreSQL could do enough of that work on its own to keep an architecture simpler for longer. That includes search, queues, JSON-heavy data, geospatial data, vector search, and other jobs that normally trigger a new box on the diagram. The broad reaction was yes, for most startups and internal tools, that instinct is directionally right. Several people went further and said the real default path is SQLite first, then PostgreSQL when concurrency, team size, or operational needs force the upgrade.

Defaulting to SQLite or PostgreSQL is still a strong startup move, but only if you keep your escape hatches open. Treat extra infrastructure as something to justify with a specific workload, not something to add because the architecture diagram looks mature.

Discussion mood

Mostly positive about PostgreSQL as the default database and skeptical of premature specialization. The mood turned negative around stored procedures, triggers, and overloading one database with too much application logic or too many mixed workloads.

Key insights

  1. 01

    SQLite is the real starting point

    For many new products the more useful simplification is not "just use Postgres" but "start with SQLite and move up only when you must." That reframes the whole piece. A lot of software never needs a networked database at all, and teams can avoid an entire layer of ops until concurrency or deployment needs become real.

    If you are building a small SaaS, internal tool, or single-binary app, test whether SQLite gets you to launch faster. Make the upgrade path to PostgreSQL explicit, but do not pay the operational cost on day one out of habit.

      Attribution:
    • SwellJoe #1
    • ammo1662 #1
    • Imustaskforhelp #1
  2. 02

    Old scaling instincts are now outdated

    Much of the advice that pushed teams toward sharding, NoSQL, or distributed architectures was formed when machines were far weaker. Faster CPUs and cheaper memory moved the boundary. Systems that looked reckless on one box a decade ago are now routine, which means many "future-proof" designs are solving yesterday's hardware limits instead of today's business needs.

    Re-run your architecture assumptions against current hardware prices and database performance, not inherited war stories. If a larger machine or better indexing solves the problem, do that before designing distributed complexity into the product.

      Attribution:
    • nemothekid #1
    • cyberax #1
    • jghn #1
  3. 03

    Database-backed queues solve consistency first

    The best defense of using Postgres as a queue was not convenience. It was transactional integrity. When work items are part of the same state change as your core data, keeping them in Postgres avoids the awkward gap between committing business data and publishing to a broker. In practice, many teams end up with a transactional outbox anyway, which means they already built a queue inside the database.

    If your jobs are tightly coupled to row-level state changes, start with an outbox or queue table in PostgreSQL. Move to SQS, RabbitMQ, or Kafka when messaging becomes an independent subsystem with its own throughput and delivery requirements.

      Attribution:
    • drdexebtjl #1
    • zarzavat #1
    • dewey #1
  4. 04

    One database also means one blast radius

    The operational case against "Postgres for everything" is not that multiple systems are always easier. It is that collapsing everything into one cluster ties unrelated workloads to the same failure domain. Resource contention, cache pressure, or a bug in one path can drag down login, search, jobs, and core transactions together. Simplicity at small scale can become fragility at high scale.

    Watch for signs that different workloads need isolation before you have an outage that proves it for you. Separate systems are justified when they reduce contention and let you scale or recover one function without taking the rest of the product with it.

      Attribution:
    • cortesoft #1
    • fyredge #1
  5. 05

    Keep application logic out of the database

    People were far more comfortable using PostgreSQL as a storage and coordination layer than as an application framework. The recurring failure mode was business logic spread across triggers, stored procedures, and schema changes that are harder to version, review, roll back, and debug than ordinary code. Database features are powerful, but once they become the main home of product behavior, change gets slower and incidents get nastier.

    Use SQL, constraints, and transactions aggressively, but keep business workflows in normal application code unless you have a narrow reason not to. If you do add database functions, hold them to the same migration, test, and observability standards as production code.

      Attribution:
    • clncy #1 #2
    • efficax #1
    • ronbenton #1
    • jamesfinlayson #1
    • christophilus #1

Against the grain

  1. 01

    Use a real queue sooner

    The case for a separate queue is that queue traffic is not just another table with inserts and deletes. It has churn-heavy access patterns that can force early tuning of autovacuum, partitioning, and indexing. Purpose-built systems like SQS, RabbitMQ, or Kafka may be simpler overall once background work is a visible part of the product, even if Postgres can technically carry it for a while.

    Measure queue churn separately from core database load. If workers become a central workload, price the operational cost of a dedicated queue against the tuning burden you are starting to absorb inside PostgreSQL.

      Attribution:
    • mikeocool #1
    • a_conservative #1
    • Joel_Mckay #1
  2. 02

    Redis can be the simpler hot-path fix

    The pushback on the anti-Redis stance was practical. For some latency problems, a hosted Redis with straightforward time-to-live based caching is easier to ship than inventing the right materialized view, refresh schedule, or table strategy inside Postgres. That is not a defense of adding infrastructure by default. It is a reminder that the simplest system is sometimes the extra one with the clearest behavior.

    When a performance bottleneck is isolated and read-heavy, compare a small cache layer against database-side optimization instead of treating one as obviously cleaner. Pick the option your team can debug at 2 a.m., not the one that wins an architecture purity argument.

      Attribution:
    • fastball #1 #2
    • mindwok #1
    • guhidalg #1
  3. 03

    Some workloads really are outside Postgres

    A few comments rejected the broad claim outright for domains like dense numerical simulation grids and very large time series workloads. Even when PostgreSQL can be extended with tools like TimescaleDB, that can effectively mean adopting another specialized system behind the familiar interface. The slogan breaks down once storage layout and access patterns are the main problem.

    Do not let the convenience of a familiar SQL frontend hide a mismatch in workload shape. If your system is fundamentally time series, simulation, or another specialist domain, evaluate purpose-built storage early enough that migration is still cheap.

      Attribution:
    • seeg #1
    • efficax #1 #2

In plain english

autovacuum
A PostgreSQL background process that cleans up dead rows and updates statistics so performance stays healthy.
Elasticsearch
A search and analytics engine commonly used for full-text search and log analysis.
Kafka
Apache Kafka is a distributed event streaming and messaging platform used for high-throughput data pipelines and event processing.
materialized view
A precomputed database query result stored as data so reads are faster than recomputing the query every time.
NoSQL
A broad category of databases that do not primarily use the relational SQL model and often optimize for specific data patterns or scale models.
PostgreSQL
A widely used open source relational database system known for strong SQL support, transactions, and extensibility.
RabbitMQ
A message broker used to route and deliver messages between software components.
Redis
An in-memory data store often used for caching, queues, and fast key-value lookups.
ScyllaDB
A distributed NoSQL database designed for high throughput and low latency at large scale.
sharding
Splitting one logical database across multiple machines or instances so each holds only part of the data.
Snowflake
A cloud data warehouse used for large-scale analytics and business intelligence workloads.
SQLite
A lightweight embedded SQL database that stores data in a local file and runs inside the application process instead of as a separate server.
SQS
Amazon Simple Queue Service, a managed cloud message queue from Amazon Web Services.
transactional outbox
A pattern where an application writes a message record into the same database transaction as its business data, then publishes it later to a broker.

Reference links

Queueing with PostgreSQL

  • pgque
    Referenced as a project that helps run worker queues on PostgreSQL.
  • Absurd in Production
    Linked as an example of practical tooling and experience around unusual PostgreSQL-backed production patterns.

Apps and projects mentioned

  • mirror.forum
    Shared as a single-binary site built with SQLite to illustrate how far an embedded database can go.
  • limereader.com
    Shared as a recent project using SQLite and Swift on the backend.

Media references

Related reading