portfolio Anshul Bisen
ask my work

Why I chose PostgreSQL over MongoDB and how it shaped our entire fintech stack

Every fintech startup I talked to was defaulting to MongoDB. I went the other way and bet on PostgreSQL with strict schemas from day one.

Every fintech startup I talked to in late 2023 was running MongoDB. The pitch was always the same: flexible schemas let you iterate fast, document models map naturally to JSON APIs, and you can always add structure later. I heard that last part so many times it started sounding like a prayer. You can always add structure later. Except in fintech, later arrives on the first day you process a real payment and your reconciliation numbers do not add up because somebody stored an amount as a string in one document and a number in another.

I chose PostgreSQL for FinanceOps before we wrote a single line of application code. Not because it was trendy, not because I had years of Postgres experience. I chose it because when you are handling other people’s money, schema rigidity is not a constraint. It is a feature. The database should refuse to accept garbage data, loudly, before it ever touches a ledger entry.

Where the data model or query started fighting back.

In that first stretch at FinanceOps, I was still learning how to wear the Head of Engineering title without hiding behind it. The only credibility that mattered was whether the decision survived contact with real money, ugly edge cases, and the next person I would eventually hire. That same bias toward strict boundaries later shaped how I approached ftryos and pipeline-sdk: make correctness boring before you make the API clever.

The operational artifact behind the argument.

The Decision Matrix

I sat down with a spreadsheet and scored MongoDB and PostgreSQL across eight criteria weighted by our specific needs. I was not trying to find the objectively better database. I was trying to find the right database for a pre-seed fintech startup that would be processing real financial transactions within three months.

  • Data integrity guarantees: PostgreSQL won by a mile. CHECK constraints, foreign keys, exclusion constraints, and transactional DDL meant the database itself enforced our business rules.
  • ACID transactions: Both support transactions but PostgreSQL serializable isolation is battle-tested across decades of financial systems. MongoDB multi-document transactions arrived in 4.0 and still carry caveats.
  • Ecosystem maturity in fintech: Every payment processor, bank integration, and compliance tool I evaluated had first-class PostgreSQL support. MongoDB support was often a community plugin or a wrapper.
  • Query flexibility: PostgreSQL with JSONB gives you document-style flexibility when you actually need it without sacrificing relational integrity for everything else.
  • Operational simplicity: Single PostgreSQL instance versus a MongoDB replica set. At our scale this mattered more than people admit.
  • Hiring: Every backend engineer I interviewed knew SQL. About half had meaningful MongoDB experience.
  • Tooling and observability: pganalyze, pg_stat_statements, EXPLAIN ANALYZE. The PostgreSQL observability story is decades ahead.
  • Cost: Managed PostgreSQL on every cloud provider costs less than managed MongoDB at equivalent specs.

PostgreSQL scored higher on six out of eight criteria. MongoDB won on initial development speed for unstructured data and on native JSON ergonomics. Neither of those advantages survived past the first month of real financial data.

Where Schema Rigidity Saved Us

Three weeks into production we received a webhook from our payment processor with an amount field formatted differently than their documentation specified. Instead of cents as an integer, they sent dollars as a string with a decimal point. Our application layer parsed it, converted it, and tried to insert it into a column typed as integer representing cents. PostgreSQL rejected the insert immediately with a type mismatch error.

That rejection triggered an alert. I investigated, found the discrepancy, added a normalization layer in our webhook handler, and contacted the payment processor about their documentation inconsistency. The entire incident took forty minutes from alert to resolution. Zero bad data entered our system.

In a schema-less database, that string would have been stored silently. We would have discovered it days or weeks later when a reconciliation report showed a $1,247.00 discrepancy that nobody could trace. I have talked to three other fintech founders who had exactly this experience with MongoDB. One of them spent two weeks debugging a reconciliation gap caused by a single malformed document.

We hit similar situations four more times in the first quarter. Currency codes stored in different cases. Timestamps with inconsistent timezone offsets. Account IDs with leading zeros that got silently stripped. Every time, PostgreSQL constraints caught it at the boundary. The database was our first line of defense and it never let bad data through.

The JSONB Escape Hatch

The argument I hear most often for MongoDB is flexibility. What happens when your schema changes? What about semi-structured data? What about metadata that varies per client? PostgreSQL has a clean answer for all of these and it is JSONB.

CREATE TABLE payment_metadata (
payment_id UUID REFERENCES payments(id),
processor_data JSONB NOT NULL DEFAULT '{}',
CONSTRAINT valid_processor CHECK (
processor_data ? 'processor_name'
AND processor_data ? 'external_id'
)
);

We use JSONB for exactly two things: payment processor metadata that varies by provider, and client-specific configuration blobs. Everything else is strictly typed columns with constraints. The JSONB columns have partial indexes on the fields we query most and CHECK constraints that enforce minimum required keys. We get document flexibility exactly where we need it and relational integrity everywhere else.

The Lesson

Choosing a database for fintech is not a technical decision. It is a risk management decision. MongoDB optimizes for developer convenience. PostgreSQL optimizes for data correctness. When you are handling money, correctness is not a nice-to-have. It is the product. Every schema constraint I wrote in those first weeks was a bug that never happened, an incident I never had to investigate, and a customer whose money was never miscounted.

The system after the boring-but-correct fix.

Looking back, this is one of those builder-phase decisions that bought me leadership credibility before I had any leadership title equity. I was still proving I could be trusted with the boring, consequential calls. That instinct carried straight into ftryos and pipeline-sdk.

In fintech, your database schema is your first compliance officer. Make it strict, make it loud, and never apologize for rejecting bad data.