PostgreSQL
The default operational database for every business system we build.
PostgreSQL sits under nearly every operational system we build. The reason is not novelty — it is that business systems are relational, they need genuine constraints and transactions, and they need to answer reporting questions years after the code that wrote the data was last touched. Postgres does all three, reliably, for decades.
It has also quietly absorbed capabilities that used to require separate systems: JSONB for semi-structured data, full-text search, geospatial through PostGIS, time-series through TimescaleDB, and vector similarity through pgvector. For a great many applications this means one database instead of four, which is a substantial reduction in operational surface.
The decision we defend most often is choosing it over a document database. A schema-less store feels faster in week two and considerably slower in year two, when every query must defend against six historical shapes of the same record. We have been called in to unwind that more than once.
Where it fits
What PostgreSQL genuinely gives us
Constraints that actually hold
Foreign keys, checks and unique constraints enforced by the database mean bad data cannot enter regardless of which application wrote it.
Transactions you can rely on
Multi-table operations either complete or do not, which is non-negotiable for anything touching money or stock.
One database, several jobs
JSONB, full-text search, PostGIS, TimescaleDB and pgvector reduce the number of moving parts a small team must operate.
Portable and unowned
Runs on any cloud, on-premise, or on a laptop, with no licence and no vendor able to change the terms.
Reading query plans instead of guessing
Most database performance advice circulating in this market is folklore, and following it produces indexes that are never used and rewrites that change nothing. The only reliable method is to look at what the planner actually does, and it will tell you plainly if asked.
EXPLAIN ANALYZE with buffers shows the real plan, the real row counts against the estimates, and where the time went. The most informative signal is usually the gap between estimated and actual rows: when the planner expects fifty rows and finds fifty thousand, it has chosen a strategy appropriate to a small result and the fix is often statistics or a rewritten predicate rather than a new index.
From there the common findings repeat. A sequential scan on a large table where a filter should be indexed. An index that exists but cannot be used because the query applies a function to the column. A nested loop join that is fine at test-data volumes and disastrous at production ones. Sorting done on disk because work_mem is too small for the query. Each has a specific remedy, and none of them are discoverable by reading the query and forming an opinion.
We also track this over time rather than case by case, using pg_stat_statements to find the queries that consume the most total time. That ranking is frequently surprising: the slow report everyone complains about often matters less than a fast query executed forty thousand times an hour.
Postgres will take you much further than you have been told
A recurring and expensive pattern in this market is a company adopting three specialist datastores before their main database has been asked to do any real work. Postgres handles relational data, JSON documents with full indexing, full-text search in several languages, geospatial queries through PostGIS, time-series through partitioning or TimescaleDB, queues through SKIP LOCKED, and increasingly vector similarity through pgvector. For the overwhelming majority of businesses, one well-run Postgres instance replaces a stack of services and removes an entire class of consistency problems that arise the moment the same fact lives in two systems.
Where teams get into difficulty is operations rather than features. Migrations run without regard for locking, so a schema change takes an exclusive lock on a large table during business hours and the application stops. Indexes accumulate faster than queries do, slowing every write. Autovacuum is left at defaults on tables that turn over aggressively, and one day transaction ID wraparound becomes an emergency. Connections are opened per request with no pooler until the server runs out.
Our Postgres work is mostly this operational layer: safe migration patterns that never take a long lock, index sets justified by query plans rather than by intuition, autovacuum tuned per table, connection pooling in front, and a backup strategy that has actually been restored from in a rehearsal rather than merely configured.
Schema decisions with the longest half-life
The database schema outlives every other decision in a system. Frameworks get replaced twice before the core tables change. So we spend disproportionate time on it: correct normalisation with deliberate denormalisation where reporting demands it, natural versus surrogate keys chosen consciously, and audit columns on every table that matters.
Every business-critical table carries who changed what, when, and what the previous value was. This is not a compliance nicety; it is what allows a disputed figure to be reconstructed eight months later without an argument.
Performance work that actually moves the needle
Almost every slow Postgres system we inherit has the same three problems: missing indexes on foreign keys and filter columns, N+1 query patterns from an ORM, and connection pool settings left at defaults. Fixing those usually accounts for most of the available improvement.
Beyond that, we read query plans rather than guessing, add partial and composite indexes where the access pattern justifies them, partition tables that have grown past comfortable maintenance size, and put reporting on a read replica so an analyst's query cannot slow down order entry.
How PostgreSQL projects usually go wrong
These are the failure modes we look for first when we are called in to rescue somebody else's implementation.
PostgreSQL questions we get asked
Including where we would recommend something other than PostgreSQL. Call +91 70033 91355 and you will get the same answer from an engineer.
PostgreSQL for anything with complex relationships, analytical queries, or a need for advanced types. MySQL is entirely capable and remains sensible where an existing team knows it well or where a platform such as WordPress or a specific hosting arrangement assumes it. For a new business system with no constraint, we choose Postgres — the constraint handling, query planner and extension ecosystem are meaningfully stronger.
Almost certainly. We run Postgres instances with hundreds of millions of rows serving transactional workloads without difficulty. The techniques that matter are partitioning, indexing discipline and a read replica for reporting. The point where you genuinely outgrow it for analytics is where a warehouse belongs anyway — and that is a different tool, not a bigger version of the same one.
Yes, and the licence saving is usually the driver. The work is mostly in translating stored procedures and handling semantic differences — empty string versus null, date behaviour, collation. We run both systems in parallel with row-level reconciliation until they match exactly, then cut over with a tested rollback. Typical cutover downtime on our recent migrations has been under five minutes.
Services built on PostgreSQL
Technologies we pair it with
Tell us what is slowing your business down.
A 30-minute call with a senior engineer — not a salesperson. You leave with an architecture sketch and an honest cost range, whether or not you hire us.
Direct line
+91 70033 91355Mon–Sat · 9:30 AM – 7:30 PM IST · Sealdah, Kolkata