Skip to content
Connect Dots
Product EngineeringApril 28, 20268 min read

How to ship an MVP you won't have to rewrite

Speed and durability are not opposites. A handful of decisions, made early and cheaply, let you move fast now without signing up for an expensive rewrite in a year.

Every founder has heard the advice to just ship fast. Most have also lived the sequel: the product that won its first users, then buckled because the foundation underneath it could not carry them.

Speed and durability are not opposites. A handful of decisions, made early and cheaply, let you move fast now without signing up for an expensive rewrite in a year.

Here is what those decisions are, what a rewrite actually costs so you can price the risk, and what you can safely leave out.

The MVP that cannot grow up

The failure mode is familiar: to hit a deadline, the team takes shortcuts that feel harmless in the moment, a tangle of special cases here, a copy-pasted module there. It works, it ships, it gets traction.

Then every new feature takes longer than the last, bugs multiply, and onboarding a new engineer takes weeks. Change amplification sets in: a one-line requirement touches eight files. Eventually someone says the dreaded words: we should just rewrite it.

What a rewrite actually costs

A full rewrite of a product that has been in market for a year typically runs 6 to 18 months, during which the team ships little or no new customer value. Competitors do not pause. The knowledge encoded in the old code's edge cases, the ones that took real production incidents to discover, is easy to lose in the rewrite and expensive to rediscover.

The alternative is almost always incremental: strangle the bad parts one module at a time behind stable interfaces, while the product keeps evolving. That is only possible if the foundation supports it, which is the whole point of getting a few things right early.

The decisions worth making on day one

You avoid the rewrite not by over-engineering, but by getting a small set of foundational things right while they are still cheap. None of these slow you down meaningfully up front; all of them compound as the product grows.

  • A typed language or strict type checking. It catches a whole class of bugs for free and, more importantly, makes large refactors safe rather than terrifying.
  • Clear module boundaries. Organize by feature or domain, not by technical layer, so a change stays inside one folder instead of rippling across the app.
  • Automated tests on the critical paths only. Not 100 percent coverage: the signup, payment, and core-workflow paths, so you can change things quickly without fear.
  • Continuous deployment from the first week. 'Done' should always mean 'in production behind a flag', never 'works on my machine'.
  • Structured logging and error tracking from day one. You cannot fix what you cannot see, and retrofitting observability after an incident is painful.
  • One database, well-modeled, with migrations in version control. Schema discipline early is far cheaper than untangling it under load later.

Boring technology on purpose

Every new technology in the stack is a cost: something to learn, patch, hire for, and debug at 3am. An MVP should spend its novelty budget on the product, not the infrastructure.

In practice that means a mainstream framework, a relational database as the default, a managed platform for hosting, and the smallest number of moving parts that does the job. Reach for the exotic option only when a real, measured constraint forces you to, and write down why.

Boring technology is well-documented, widely understood, and unlikely to surprise you. That is exactly what you want under a product that is changing every week.

What you can safely skip

Just as important is what to leave out. Premature abstractions, speculative scaling for users you do not have yet, microservices before you have a monolith worth splitting, and gold-plating features nobody has asked for are where real time gets wasted.

The rule of thumb: solve the problem in front of you in the simplest way that will not actively block the next step. A single well-structured application will carry most products to a meaningful scale. You will know when you have outgrown it, and by then you will have the revenue and the information to do the split properly.

The goal is a product that is simple today and cheap to change tomorrow, not one that tries to anticipate every future requirement and collapses under the weight of guesses.

Ship behind a flag

Feature flags let you merge and deploy work continuously while controlling what users actually see. You can release to a handful of people, watch the logs and metrics, and roll back instantly if something is wrong, without a deploy.

That turns launches from high-stakes events into routine, reversible steps. A small team can then move fast precisely because mistakes are cheap to undo, which is what protects user trust while you are still figuring the product out.

Keep the flag system simple: a config table and a helper function is enough to start. Clean up stale flags every few weeks so they do not become their own tangle.

Instrument the product, not just the servers

Server metrics tell you the app is up. Product analytics tell you whether anyone is getting value from it. From the first release, capture the handful of events that describe your core loop: signed up, completed setup, performed the key action, came back the next day.

You do not need a heavy analytics stack for this. A single events table and a few well-named event types will answer most early questions, and it keeps the data in your own database where you can join it to everything else.

The point is to make 'is this working' a query, not a debate. Teams that skip this end up arguing from anecdote for months.

Write down the decisions you are deferring

Every shortcut is a loan. The problem is not taking the loan, it is forgetting you took it. Keep a short list, in the repo, of the deliberate simplifications: the in-memory queue that will need to become a real one, the single-region deployment, the auth that assumes one organisation per user.

Each entry says what the simplification is, what will force you to revisit it (a user count, a customer type, a compliance requirement), and roughly what the upgrade looks like.

This turns 'technical debt' from a vague anxiety into a backlog you can prioritise, and it means the person who hits the limit in six months is not starting from archaeology.

Key takeaways

  • A rewrite costs 6 to 18 months of stalled roadmap; price that risk before taking shortcuts.
  • Get types, feature-based module boundaries, and critical-path tests right on day one.
  • Deploy to production continuously from week one, behind feature flags.
  • Add structured logging and error tracking before you need them, not after an incident.
  • Choose boring, well-understood technology and spend your novelty budget on the product.
  • Skip premature abstractions, speculative scale, and microservices until a real constraint forces them.
Written by Connect Dots

Have an idea worth connecting?

Tell us what you're building. We'll bring the engineering to match the ambition.

Get in Touch