Skip to content

Engineering

The Only Technical Debt Acceptable in an MVP

The distinction between borrowed debt that speeds delivery and toxic debt that requires a total rewrite. A practical categorization framework.

Dhanji Bhagat

Dhanji Bhagat

Founder & Principal Engineer

5 min read
technical debtMVParchitectureproduct

When founders and engineers discuss building an MVP in twenty-eight days, the first question is usually about technical debt.

Will cutting timeline force us to write disposable code? Will we have to throw the software away and start over once we get our first thousand users?

The answer depends on understanding what technical debt actually is. Ward Cunningham originally coined the metaphor to describe a deliberate financial loan: you borrow speed today to validate an idea with real users, knowing that you will pay back the principal with interest once the market confirms the opportunity.

Problems occur when teams do not differentiate between borrowed debt and toxic debt.

Borrowed debt speeds up learning and can be repaid in clean, incremental refactors. Toxic debt poisons the data layer, introduces silent corruptions, and forces teams into painful ground-up rewrites.


Borrowed debt vs Toxic debt

flowchart TD
    subgraph Borrowed["Borrowed Debt (Acceptable in MVP)"]
        B1["Manual founder operations (no admin UI)"]
        B2["Basic SQL queries without caching layers"]
        B3["Single transactional email templates"]
        B4["Synchronous report generation for small data"]
    end

    subgraph Toxic["Toxic Debt (Unacceptable in Any Release)"]
        T1["Untyped databases & missing foreign keys"]
        T2["Floating-point math for financial balances"]
        T3["Leaky tenant isolation boundaries"]
        T4["Mutations executed without database transactions"]
    end

    Borrowed --> Payoff["Repayable in Days 30 to 90 as Revenue Grows"]
    Toxic --> Rewrite["Requires Painful Ground-Up Database Rewrite"]
DimensionBorrowed Debt (Safe to Defer)Toxic Debt (Fatal to Product)
Data IntegrityStrict PostgreSQL types and constraintsLoose text fields, nullable assumptions
Financial LedgerInteger cents stored in atomic transactionsFloating-point numbers, unbalanced rows
Admin OperationsFounder runs direct SQL scripts to update usersUnauthenticated backdoor endpoints
Background ProcessingSimple cron script polling a single tableRace conditions silently dropping records
Cost to RepayTwo days of developer timeComplete database migration and data repair

The three forms of acceptable borrowed debt

When building an MVP under strict timeline constraints, here are the three areas where taking on technical debt is smart engineering:

1. Manual operations instead of bespoke admin panels

Building a custom dashboard where customer support agents can refund orders, change plan tiers, or reassign organizations takes two weeks of development time.

In week one or two, founders can execute these updates directly in a database GUI like TablePlus using prepared SQL statements:

-- Acceptable borrowed debt: Manual plan upgrade via secure SQL query
UPDATE organizations 
SET plan_tier = 'growth', updated_at = NOW() 
WHERE id = 'a8f5c31e-42b7-4d98-8e2b-7f1234567890';

Running direct queries for your first twenty customers costs twenty minutes a week. Building the full admin interface can wait until manual operations become a measurable bottleneck.

2. Basic database queries without caching layers

Do not set up Redis clusters or memcached layers for an application that gets three queries per minute.

A standard PostgreSQL query on an indexed column takes three milliseconds. Premature caching introduces cache invalidation bugs where users see stale data after updating their profile. Rely on standard PostgreSQL indexes until slow query monitoring proves that database CPU is constrained.

3. Synchronous processing for low-volume jobs

If generating a customer invoice takes 200 milliseconds, generate it synchronously during the HTTP request.

You do not need a distributed Celery or Kafka queue to process seven invoices a day. When background volume increases, extracting that logic into a background worker takes half an engineering day because the database schema remains cleanly typed.


The four forms of toxic debt: Never compromise

Some shortcuts save two hours during week one but destroy the company in month six. We reject these shortcuts in every build sprint:

1. Untyped databases and missing foreign key constraints

Using string fields for dates, storing currency as floating-point numbers (19.99 instead of 1999 cents), or skipping foreign keys to make schema prototyping faster leads to corrupted data. Once bad data enters a database, fixing it requires writing complex reconciliation scripts to guess which records belong together.

2. Missing database transactions on mutations

If an action creates a billing record and deducts inventory, both operations must occur within a single SQL transaction:

BEGIN;
INSERT INTO invoice_payments (invoice_id, amount_cents) VALUES ($1, $2);
UPDATE invoices SET status = 'paid' WHERE id = $1;
COMMIT;

Writing separate independent queries without transactions means a network hiccup leaves an invoice marked as unpaid while charging the customer.

3. Loose tenant boundaries in application code

Relying on developers to remember WHERE organization_id = $1 in every application query is a guarantee that someone will eventually forget it, exposing private customer records. Enforce isolation with PostgreSQL Row-Level Security from day one.

4. Zero automated test coverage on core financial paths

You do not need 100% test coverage on marketing pages. But the central transaction that charges cards or balances ledger entries must have automated tests. If you cannot refactor an internal function without fear of breaking payments, velocity slows to a crawl.


Borrow with intent, repay with discipline

Speed in software engineering does not come from writing reckless code. It comes from ruthlessly cutting non-essential features while keeping the foundation solid.

Borrow debt on the perimeter: skip the admin dashboard, defer custom email notifications, and keep caching simple. Never borrow debt on the data model, financial calculations, or tenant boundaries.

When your foundations are sound, scaling from fifty users to five thousand users is an orderly engineering task rather than an emergency rewrite.

To learn how we prune scope while protecting data integrity, read our MVP scope pruning framework or talk to our studio about your product architecture.

BOOK A CALL

Ready to turn your idea into a live product?

Schedule a 15-minute scoping call with Dhanji below. We'll discuss your scope, timeline, and tech strategy honestly.