Why the Second System Is Always the One That Disappoints

by Arif Ikhsanudin, Backend Developer

The Rewrite That Was Supposed to Fix Everything

The original system has accumulated three years of compromises, workarounds, and technical debt. The architecture has visible seams from decisions made when the requirements were different. The team knows exactly what's wrong with it and exactly what they'd do differently if they could start over.

So they start over.

The second system begins with tremendous confidence. This time there are no constraints from the past. Every lesson learned is incorporated. Every feature that was too hard to add to the old system will be easy to add to the new one because the architecture is flexible. The code will be clean, the design will be principled, the abstractions will be right.

Eighteen months later: the project is behind schedule. The architecture that was supposed to be flexible is complex. New requirements don't fit as cleanly as expected. Some of the problems from the first system have reappeared in different forms. And the first system, held together with duct tape, is still running in production serving actual users.

Why It Keeps Happening

Fred Brooks named the second-system effect in The Mythical Man-Month (1975). His observation: an engineer's first significant system is produced with restraint because of uncertainty. They don't know what the right approach is, so they keep it simple. The second system is built with all the confidence accumulated from the first — and with all the features and generalizations they had to restrain themselves from adding the first time.

The second system is the one where the engineer finally gets to build things "right." The problem is that "right" now incorporates every theoretical improvement they've been thinking about for years, regardless of whether those improvements are needed for the actual requirements.

The second system is over-engineered by design.

The Specific Failure Patterns

Generalizing for requirements that don't exist: The first system had three hardcoded payment providers. The second will have a plugin architecture that supports any payment provider. This sounds prudent. When you actually need a fourth payment provider — which may or may not happen — the plugin architecture takes one day to extend. Building the plugin architecture speculatively takes two weeks. And it adds complexity to every subsequent change to the payment flow.

Building infrastructure before products: The second system will have a proper event-sourcing architecture, a CQRS pattern, eventually-consistent read models. These are legitimate patterns for specific scale and complexity levels. Applied to a system that doesn't need them yet, they add significant overhead for every feature.

Incorporating all the lessons as mandatory constraints: Every workaround from the first system gets a proper solution in the second. Some of these are genuine improvements. Some were workarounds for problems that no longer exist, or that could have been fixed in the original system at a fraction of the cost of a rewrite.

When Rewrites Are Justified

Not all rewrites are the second-system trap. A rewrite is justified when:

  • The existing system's constraints make required functionality impossible or unreasonably expensive to implement
  • The codebase is so poorly understood that maintaining it is riskier than replacing it
  • The underlying technology is genuinely end-of-life with no viable migration path

In these cases, the rewrite is about solving specific, named problems — not about finally building it "right."

The Discipline That Prevents It

The antidote to the second-system effect is explicit scope discipline:

  1. Name the specific problems you're solving with the rewrite. Not "it's messy" — specific things that block specific work.
  2. Design for current requirements, not anticipated ones. The new system should solve the problems the old one had. Not the problems you imagine you'll have.
  3. Resist the wish list. Every feature that goes into the second system because "we couldn't do it in the first one" should require a product justification, not just a technical one.
  4. Maintain the first system as a working baseline until the second system demonstrably handles all of its traffic. Parallel running reveals the gaps in the second system that enthusiasm conceals during development.

The Practical Takeaway

Before committing to a rewrite, write down the specific, named problems with the current system that the rewrite must solve. Then write down every additional thing you'd like to build into the new system. Separate these lists. The rewrite scope is the first list. The second list is backlog — it goes in after the system is running and only when there's a concrete justification for each item.

Scale Your Backend - Need an Experienced Backend Developer?

We provide backend engineers who join your team as contractors to help build, improve, and scale your backend systems.

We focus on clean backend design, clear documentation, and systems that remain reliable as products grow. Our goal is to strengthen your team and deliver backend systems that are easy to operate and maintain.

We work from our own development environments and support teams across US, EU, and APAC timezones. Our workflow emphasizes documentation and asynchronous collaboration to keep development efficient and focused.

  • Production Backend Experience. Experience building and maintaining backend systems, APIs, and databases used in production.
  • Scalable Architecture. Design backend systems that stay reliable as your product and traffic grow.
  • Contractor Friendly. Flexible engagement for short projects, long-term support, or extra help during releases.
  • Focus on Backend Reliability. Improve API performance, database stability, and overall backend reliability.
  • Documentation-Driven Development. Development guided by clear documentation so teams stay aligned and work efficiently.
  • Domain-Driven Design. Design backend systems around real business processes and product needs.

Tell us about your project

Our offices

  • Copenhagen
    1 Carlsberg Gate
    1260, København, Denmark
  • Magelang
    12 Jalan Bligo
    56485, Magelang, Indonesia

More articles

Spring Boot Logging in Production — Structured Logs, Correlation IDs, and What to Alert On

Unstructured logs are difficult to query and impossible to alert on reliably. Structured logging with consistent correlation IDs and the right log levels transforms logs from a last resort into a first-line diagnostic tool.

Read more

The Machine Behind My Backend Systems

This is the setup we use to deliver backend work that’s fast, reliable, and efficient. Optimized tools help us build systems anywhere, anytime, without compromise.

Read more

Your API Contract Is a Promise. Stop Breaking It.

An API that changes without warning is not an API — it is a liability. Versioning, deprecation, and backward compatibility are not bureaucratic overhead; they are the baseline respect you owe to every caller of your service.

Read more

Your Portfolio Is Not Just Your Work. It Is Your Argument for Being Hired.

A portfolio that lists what you built is not the same as a portfolio that explains why a client should trust you. The difference is in how you frame the story.

Read more