Database

Why PostgreSQL Is Still the Right Database for 95% of South African Startup Prototypes in 2025

The Lead Architect 10 min read April 2025

Every 18 months, a new database technology arrives with a compelling pitch: horizontal scale, flexible schemas, developer experience, or some combination of all three. DynamoDB promised internet-scale key-value reads. MongoDB promised schemaless flexibility. Cassandra promised write throughput that relational databases could not touch. Redis promised in-memory speed for everything. Each of these databases is genuinely excellent at solving a specific class of problem. None of them is the right first choice for a South African fintech startup prototype.

PostgreSQL has been in continuous production use since 1996. It is the default database engine for a reason that has nothing to do with nostalgia: it is the most capable general-purpose database that exists, and for the class of problems that startup prototypes actually have, it is almost always sufficient without being limiting.

The NoSQL Hype Cycle and the Problem It Masked

The NoSQL movement emerged from a real problem: relational databases at the scale of Google, Amazon, and Facebook were genuinely constraining. When you are storing billions of user events across thousands of servers, the locking semantics and join overhead of a relational database become genuine bottlenecks.

The mistake was generalising from that problem. A South African fintech startup with 10,000 active users does not have a web-scale problem. It has a business problem — acquiring users, maintaining regulatory compliance, processing payments reliably, and not running out of money. PostgreSQL solves all the database needs of that business. MongoDB does not add value at that scale. DynamoDB adds operational complexity that a small team will spend engineering effort managing rather than building product.

The question to ask when choosing a database is not "what can handle the most data?" It is "what is the simplest technology that will not be the bottleneck between now and 100,000 users?" For 95% of South African startup prototypes, the honest answer is PostgreSQL.

What You Actually Need in a Startup Database

Before picking a database, define the requirements. For a fintech prototype operating in the South African regulated environment, those requirements are:

PostgreSQL Features That Matter for Fintech

Row-Level Security (RLS)

PostgreSQL's Row-Level Security policies allow you to enforce data isolation at the database layer — not just in application code. In a multi-tenant fintech platform (e.g., a white-label lending product with multiple origination partners), RLS ensures that a query from Tenant A's application role physically cannot return Tenant B's records, even if the application has a bug:

-- Enable RLS on the accounts table
ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;

-- Policy: users can only see their own accounts
CREATE POLICY accounts_tenant_isolation
    ON accounts
    USING (tenant_id = current_setting('app.current_tenant_id')::uuid);

-- Application sets the tenant context on each connection
SET LOCAL app.current_tenant_id = '550e8400-e29b-41d4-a716-446655440000';

JSONB for Semi-Structured Data

Credit bureau response payloads, KYC provider webhooks, payment gateway callbacks — these arrive as JSON with evolving schemas. JSONB stores them in a binary format with full GIN index support, meaning you can run WHERE payload @> '{"status": "APPROVED"}' and have it use an index. You do not need a separate document store for this use case.

pgcrypto for Column-Level Encryption

As covered in the POPIA compliance article, pgcrypto enables symmetric encryption of sensitive columns (ID numbers, bank account details) at the database level, with keys managed outside the database via AWS Secrets Manager. The encryption is transparent to the application when the session key is set correctly.

Logical Replication

When you eventually need a read replica for reporting queries (and you will, once your analytics team starts running multi-second aggregate queries that compete with your API), PostgreSQL's logical replication sets it up in under an hour on RDS. You point your reporting service at the replica connection string and your production API is isolated from analytical load.

PostGIS for Location Data

If your product involves any location component — geofencing for merchant presence detection, branch finder, delivery radius — PostGIS turns PostgreSQL into a capable geospatial database. ST_DWithin, ST_Distance, and spatial indexes handle the kind of location queries most fintech products need without adding a separate geospatial service.

Honest Cost Comparison

Technology choices have cost implications. Here is a rough but honest comparison of managed database costs at three scale points, using 2025 AWS pricing in USD (converted to ZAR at approximately R18.50/USD):

At 10,000 active users (~50 GB data):
AWS RDS PostgreSQL db.t4g.medium (Multi-AZ): ~$70/month (~R1,300/mo)
MongoDB Atlas M10: ~$60/month (~R1,110/mo)
DynamoDB (on-demand, 10M reads/writes): ~$15/month but operational complexity cost is real
Verdict: Cost parity at low scale. PostgreSQL wins on operational simplicity.

At 100,000 active users (~500 GB data):
AWS RDS PostgreSQL db.r6g.large (Multi-AZ): ~$280/month (~R5,200/mo)
MongoDB Atlas M30: ~$540/month (~R10,000/mo)
DynamoDB (provisioned, aggressive caching): ~$150/month but requires architectural investment
Verdict: PostgreSQL is materially cheaper. MongoDB Atlas scales cost faster than value for this workload type.

At 1,000,000 active users (~5 TB data, high write throughput):
At this scale, workload characteristics matter more than the database name. PostgreSQL with read replicas and connection pooling (PgBouncer) handles most financial application workloads to this scale. If you are at 1 million active users on a South African fintech product, you have multiple engineering options and the budget to evaluate them properly.

When PostgreSQL Is NOT the Right Choice

Being honest matters more than being a fanboy. There are genuine use cases where PostgreSQL is the wrong tool:

If your product genuinely has one of these requirements, use the right tool. Most South African fintech prototypes in 2025 do not have these requirements in year one.

The Entity Framework Core + Dapper Hybrid Pattern

This is the pattern every Foundation Sprint prototype ships with, and it has proven itself across multiple real engagements. EF Core handles the things it is genuinely good at: migrations, entity mapping, CRUD operations with change tracking. Dapper handles the things EF Core is awkward at: complex multi-table reporting queries, bulk operations, and anything where you want to write the SQL yourself.

// EF Core for standard CRUD — generates safe parameterised SQL
public async Task<Application> CreateApplicationAsync(Application application)
{
    _context.Applications.Add(application);
    await _context.SaveChangesAsync();
    return application;
}

// Dapper for complex reporting — write the SQL you actually need
public async Task<IEnumerable<LoanPortfolioReport>> GetPortfolioSummaryAsync(
    Guid tenantId, DateOnly reportDate)
{
    const string sql = """
        SELECT
            p.product_name,
            COUNT(a.id)                         AS total_applications,
            SUM(a.loan_amount)                  AS total_disbursed,
            AVG(a.interest_rate)                AS avg_rate,
            COUNT(a.id) FILTER (WHERE a.status = 'DEFAULT') AS defaults
        FROM applications a
        JOIN products p ON p.id = a.product_id
        WHERE a.tenant_id = @TenantId
          AND a.disbursed_at::date <= @ReportDate
        GROUP BY p.product_name
        ORDER BY total_disbursed DESC;
        """;

    using var conn = _connectionFactory.CreateConnection();
    return await conn.QueryAsync<LoanPortfolioReport>(sql,
        new { TenantId = tenantId, ReportDate = reportDate });
}

The rule is simple: if EF Core generates the query correctly and efficiently, use EF Core. If you find yourself fighting with .Include() chains and AsNoTracking() to produce a query that is still not what you want, switch to Dapper and write it. Both live in the same repository, share the same connection factory, and are tested the same way.

The Investor-Ready Database Argument

This is not a soft argument. It is commercial reality in the South African market. When a fintech startup goes through due diligence for a seed round, a banking partnership, or a payment service provider onboarding process, the technical reviewers are financial systems professionals. They understand relational schemas. They can read an entity-relationship diagram. They know what a foreign key constraint is and why it matters.

A PostgreSQL schema with proper normalisation, clearly named tables, foreign key constraints, and documented indexes communicates engineering discipline. A DynamoDB single-table design, while valid and even elegant for the right workload, requires significant explanation and raises questions about whether the team understood the trade-offs they were making. A MongoDB collection with 47 different document shapes because the schema "evolved organically" is a due diligence red flag.

The auditors who review your system before a Deloitte sign-off or an FSP licence application understand SQL. They have been reading it for 20 years. Give them a database they can read.

The Bottom Line

PostgreSQL is not the default choice because of inertia. It is the default choice because it is genuinely excellent at the things South African fintech startups need: ACID transactions, rich queries, POPIA-relevant security controls, mature tooling, and a total cost of ownership that does not scale faster than your revenue. When a specific workload genuinely requires a different tool, use the right tool. Until then, stop chasing novelty and start shipping.

See the full reference stack in action

Every Foundation Sprint delivers a production-grade prototype on the same reference stack: .NET 10, PostgreSQL on AWS RDS, ECS Fargate, and Terraform — all wired together from day one.

See our full reference stack
← Back to The Architect’s Blog