PostgreSQL
Boring is a feature, and Postgres is our default
We run Postgres directly, through Supabase and through Neon's serverless tier, across systems handling shop operations, clinical trial matching and workforce data. This is what running it in production has taught us.
The short answer
Postgres is the right default database for almost any product, and the exceptions are narrow enough that you should be able to name yours before reaching for something else.
Choose differently in two situations. A serverless deployment that opens a connection per request needs a pooler in front of Postgres, or it runs out of connections under real traffic. And a queue does not belong in a relational table just because the database is already there. We have built one system on MySQL instead of Postgres, for reasons specific to that build rather than a general preference.
What decides this
4 things that decide this
- 01Postgres is relational and open source, and it follows the database rules that keep data correct. That makes it a safe pick you rarely regret.
- 02Connection limits are the sharpest edge in serverless setups. Each function call can open its own connection, and the database runs out before the app does.
- 03Row-level security and add-ons like pgvector let one Postgres database cover access control and vector search. You do not need a second database for that.
- 04A queue is not a table. Using Postgres to hold job state works at small scale. At real volume, it turns into a locking problem.
A relational database that has been the safe default for three decades
PostgreSQL is an open-source relational database. Data lives in tables that link to each other, and you get it back out with SQL, a query language most engineers already know. None of that is new. That is the point.
What keeps it current is the range of add-ons. pgvector adds vector search for AI retrieval, with no separate vector database needed. PostGIS adds location queries. Row-level security sits inside the database itself, so access rules live next to the data they protect, not scattered through app code. One database now covers ground that used to need three.
Where it holds up, and the trade-offs that remain
Strengths
- Standard SQL and a huge hiring pool. Nobody joins a team and has to learn a new query language first.
- Add-ons cover ground that would otherwise need a second system: pgvector for AI retrieval, PostGIS for location data, row-level security to keep tenants apart.
- It scales further than most teams expect, and read replicas cover most of the growth before harder work like sharding is ever needed.
- No vendor lock-in. A Postgres database moves between Supabase, Neon, RDS and a self-hosted server with a dump and restore, not a rewrite.
Trade-offs
- Connection limits bite hard in serverless setups. Without a pooler in front of it, a burst of function calls uses up every connection and requests start failing.
- It is not a queue. We have seen job tables that worked fine at low volume start locking up once background jobs ran into the thousands per hour. We moved that work onto Redis instead.
- Scaling up has a ceiling. At real write volume, splitting a relational database across servers is hard engineering work that a document store puts off longer.
- Migrations on a large table can lock it. A schema change that looks small can hold a table longer than a team expects, if nobody plans it around live traffic.
- Function invokedEach cold start opens a new connection
- No poolerConnections go straight to Postgres
- Traffic burstConcurrent invocations multiply connections
- Limit hitPostgres refuses new connections
- Requests failNot a Postgres bug, a missing pooler
This is the single most common way a serverless team blames the database for a problem in their own connection handling. A pooler in front of Postgres, run by the platform or self-managed, is what prevents it.
What we actually run, and the one time we did not
ZhoopZhoop runs Postgres directly under a FastAPI backend, holding shop operations and parts procurement for a multi-branch auto repair business. WAIQ runs it the same way for multi-site business operations and execution tracking. Both connect from a long-running server process, so the serverless connection problem never applies.
ExtraaJe runs Postgres through Supabase, using row-level security to keep each employee's data apart on a European workforce platform. TrialTriage runs it through Neon's serverless tier, matching oncology patients to clinical trials. There, we had to plan connection pooling from the start, not add it after a traffic spike caused failures.
We built Elevent, a live multiplayer trivia platform for corporate events, on MySQL instead. That choice fit the way that system handles live sessions and leaderboards. It was not a verdict against Postgres as a whole. Boring is a feature, but it is a default, not a rule with no exceptions.
- 01A long-running server process (not serverless) removes the connection-pooling question entirely.
- 02Supabase and Neon both add pooling for you, but their defaults differ and it is worth reading which one you are on.
- 03Row-level security is worth the setup cost once more than one tenant shares a table.
Systems running on this database
What teams ask before committing
01Postgres or MySQL for a new startup?
Postgres, by default, for most products. It sticks closer to the SQL standard and has more add-ons, including pgvector for AI retrieval, which most new products end up wanting. MySQL still earns a place in some cases, such as read-heavy apps built around a simpler setup for copying data across servers.
02Is Postgres enough for a real production system, or do we need something else alongside it?
For most products, yes, on its own. Two jobs sit better outside it. Background job processing at real volume runs better on a dedicated queue such as Redis. Pure key-value caching also fits a table poorly, since a table was never designed for it.
03What breaks first as a Postgres-backed product grows?
Connection handling, almost always. This shows up most in serverless setups, where each call can open its own connection. A pooler in front of the database, planned before launch rather than bolted on after an outage, is what stops it.
04Do we need a separate vector database for AI features?
Not at moderate scale. The pgvector add-on puts similarity search into a table you already have, so retrieval sits next to the rest of your data. A dedicated vector database earns its place once search runs at a volume that starts to strain Postgres itself.

