Start With Postgres, Then Earn the Complexity

In the year of our lord 2026, it is still a little wild how quickly a new application turns into a shopping cart full of infrastructure.

A database, obviously. Then a search cluster, because searching is hard. A queue, because background work is hard. Redis, because speed. An analytics warehouse, because charts. A vector database, because it is 2026 and apparently every application needs to have a thoughtful conversation with its own invoices.

Before anyone has used the product, the architecture diagram looks like a cloud-vendor scavenger hunt.

Just use Postgres.

More precisely: start with Postgres, and make every additional system earn its way into the application. Not with “we may need this at scale,” but with a concrete requirement the database cannot meet.

This is not the argument that Postgres is secretly every kind of database. It is not. It is the argument that operational complexity is real, and a mature relational database can cover an almost rude amount of early and middle-stage application work.

Every box comes with chores

A new service is never just one more friendly logo on the diagram. It is another deployment, backup policy, access model, alert, upgrade path, incident mode, and bill. It is another thing to explain to the next engineer who joins the team.

The entertaining part begins when data has to exist in more than one place. The application writes a record to Postgres. A worker copies it to the search index. Another process invalidates a cache. Somebody notices the analytics event is missing. Now the team has a distributed-systems problem, which is a very sophisticated way to say “we are trying to keep our copies from disagreeing.”

That can absolutely be worthwhile. It is just not free because the managed-service setup wizard was pleasant.

Postgres lets a team postpone much of that ceremony. It gives you transactions, indexes, full-text search, structured queries, and support for semi-structured data in one well-understood place. That leaves more time to find out whether anyone wants the product.

The boring default has range

Most applications start with related records that need to be correct: users, accounts, permissions, orders, messages, audit logs, tasks. A relational database is not a compromise for that workload. It is the obvious tool.

It also has more room than people sometimes remember:

  • Search: Built-in full-text search may be plenty when users need to find things in your application, rather than search the internet with all the relevance expectations that implies.
  • Flexible attributes: JSONB is useful when a few fields genuinely vary, while the facts the application relies on stay in columns with types and constraints.
  • Background work: A table-backed job queue can be a practical answer for modest asynchronous work, especially when creating the job must be atomic with a database update.
  • Reporting: Indexes, aggregates, and materialized views can answer a surprising number of product and operational questions before a separate analytics pipeline becomes necessary.
  • Retrieval features: Vector extensions can make a small semantic-search or retrieval feature easier to prototype beside the records it is retrieving.

None of this means dedicated tools are fake. It means “could Postgres handle the first honest version?” is a much better question than “which six services should we provision before lunch?”

“We might need it later” is not a requirement

There is a familiar performance of technical seriousness where a team rejects the simple design because it might not survive the eventual day it has 100 million users, a global event stream, and a full-time platform group.

Maybe! That would be a great problem to have. It would also be useful to know whether the product needs 100 users first.

A specialized system should have a job description:

  • A dedicated search engine makes sense when relevance requires sophisticated ranking or faceting, indexing load is hurting the primary database, or search must be available independently of transactional traffic.
  • A message broker makes sense when workloads need durable fan-out, replay semantics, very high throughput, or consumers that scale independently.
  • A cache makes sense when the database cannot meet a known latency or read-volume target at an acceptable cost.
  • A warehouse makes sense when analytical queries should not compete with transactional work, or when the organization needs durable historical analysis across many systems.

Those are requirements. “We saw a conference talk” is a mood.

One system does not mean one terrible system

Using Postgres for more than the obvious tables is not permission to put every fact in one 400-column table called “data” and call it flexibility.

The fundamentals still matter, perhaps more so when one system is carrying a meaningful share of the application:

  1. Model stable facts explicitly. Use types, foreign keys, and constraints where integrity matters. Use flexible fields deliberately, not to avoid deciding what data means.
  2. Measure real queries. A slow query is a reason to inspect indexes and query plans before it is a reason to buy a different database.
  3. Make background work observable. A table-backed queue still needs retries, failure handling, and a clear answer for what happens when a worker disappears at 2:00 AM.
  4. Know the escape route. When a specialized service becomes necessary, decide what is authoritative, how data is copied, how correctness is checked, and what happens when synchronization falls behind.

The goal is not to prove that Postgres can be forced into every workload. Congratulations, nobody gets a medal for that. The goal is to avoid paying for distributed complexity until it pays you back.

AI can help with the code. It cannot un-move the data.

In 2026, Codex and Claude can do useful work on technical debt. They can help trace a legacy code path, draft a refactor, write tests, or turn an unpleasant migration plan into a less unpleasant set of pull requests. That is genuinely useful.

They cannot make a bad datastore decision disappear.

Once production data lives at meaningful scale in the wrong place, the hard part is rarely producing the migration script. It is moving data without losing it, corrupting it, leaking it, duplicating it, or letting two systems quietly disagree while the migration is in progress. Then there are backfills, validation, cutover, rollback, client compatibility, and the small matter of keeping the application available while all of this happens.

An AI assistant can help reason about those steps. It cannot turn a risky data migration into a harmless autocomplete exercise. The more systems that become authoritative for some slice of the product, the more expensive the eventual exit tends to be.

That is another reason to start simple. Choosing Postgres does not guarantee you will never migrate data; products change. It does mean you should not create a migration project merely because an early architecture diagram needed more logos.

Make complexity pay rent

Some applications need specialized infrastructure on day one. A search product with sophisticated relevance requirements is not going to bluff its way through with a basic text index. A high-volume eventing platform should not pretend a table queue is its final form. A real-time analytics product may have needs that are plainly not OLTP.

Fine. Use the right tool.

But most teams should be able to state the specific benefit they are buying: a reliability property, a measured performance target, or a product capability that the simpler design cannot deliver. If they cannot, the new box is probably architecture cosplay.

Postgres is not everything. It is just a very capable foundation that can let a team ship, learn, and defer irreversible decisions until there is evidence behind them.

That is less glamorous than a diagram with twelve logos. It is also often how you end up with an application instead of a collection of services that is very prepared to support one.

This post was sparked by Raphael Bauer’s “PostgreSQL for Everything”. His essay goes deeper on the capabilities that make the “start here” argument possible.