RE09 All articles
Engineering Culture

Prototype Forever: The Code You Wrote in a Weekend That Now Runs Your Business

RE09
Prototype Forever: The Code You Wrote in a Weekend That Now Runs Your Business

Somewhere in a production environment right now, there's a Python script that was never supposed to see daylight beyond a Thursday afternoon. It has no tests. The variable names are single letters. The database schema it relies on was designed by someone who, by their own admission, "just needed something that worked for the demo."

That script is probably processing real money, real user data, or real business logic. And nobody on the current team fully understands it.

This is the prototype tax. And almost every fast-moving team pays it eventually.

The Myth of the Clean Rewrite

Here's how the story usually goes. A team needs to validate an idea fast. They cut corners — intentionally, intelligently. Hardcoded values. No error handling. A database that's basically a spreadsheet in disguise. The goal is to learn, not to build.

The prototype works. Users show up. The idea gets funded or greenlit or just gains momentum. And then someone says the words that echo through engineering history: "We'll clean this up once we have more time."

More time never comes. Instead, the prototype gets a feature request. Then another. Someone wraps a new service around it. The frontend team builds against its API. A customer integration goes live. Now the prototype isn't a prototype anymore — it's infrastructure. And infrastructure, as any seasoned engineer will tell you, is forever.

The rewrite that was supposed to happen in Q2 gets pushed to Q3, then deprioritized entirely when the team has to ship a new product line. The code that was written to answer a single question ends up answering thousands of questions a day, none of which it was designed to handle.

Real Systems, Prototype Bones

This isn't a hypothetical. Talk to enough engineers at companies that scaled fast and you'll hear the same story in different flavors.

One mid-size SaaS company in the Midwest ran their entire billing reconciliation process on a script one of the founders wrote during a hackathon. For four years. They discovered this when a new engineer tried to trace a discrepancy and realized the logic lived in a file called temp_fix_v3_FINAL.py. It had no version history because it had been edited directly on the server.

Another team built a real-time notification system on top of a queuing mechanism that was originally a proof of concept for a pitch deck. When they finally audited it, they found the system had been silently dropping roughly 2% of notifications for over a year. Nobody had noticed because the failure was quiet and the metric they were watching was the wrong one.

These aren't stories about incompetent engineers. They're stories about teams moving fast in the right direction, making rational short-term decisions that compound into long-term structural problems.

Why Teams Don't Rebuild

The honest answer is that rebuilding is terrifying. You're replacing something that works — even if it works badly — with something that doesn't exist yet. The prototype has years of implicit knowledge baked into it. Edge cases that were handled by accident. Business logic that lives in the code because nobody wrote it down anywhere else.

Rewriting means reverse-engineering your own decisions from three years ago, made by people who may no longer be at the company, under constraints that no longer apply. It's expensive, it's risky, and it doesn't ship any new features.

So teams patch. They add layers around the prototype. They build abstraction on top of abstraction. The prototype becomes the core of a system that nobody fully understands, surrounded by newer code that everyone pretends is the real architecture.

Knowing When to Cut Your Losses

The question isn't whether to live with prototype code — almost everyone does, at least for a while. The question is whether you're making a conscious choice or just avoiding a hard conversation.

Here's a practical test. Ask yourself: if this component failed completely tomorrow, could your team rebuild it in a week? If the answer is no — if the knowledge is that diffuse, the behavior that undocumented, the dependencies that tangled — you're not running a prototype anymore. You're running a liability.

A few signals that it's time to take the rewrite seriously:

The bus factor is one. If only one person on your team can reason about how the system actually behaves, that's not a codebase, that's a hostage situation.

Onboarding takes longer than it should. When new engineers spend their first two weeks just trying to understand why something works, the prototype tax is showing up in your hiring costs.

You're building features around the prototype's limitations. When product decisions get made based on what the old code can handle rather than what users need, the tail is wagging the dog.

Incidents keep tracing back to the same root. If your postmortems keep pointing at the same component — the one everyone half-understands — the problem isn't bad luck.

A Smarter Way to Validate

The goal isn't to stop building prototypes. Prototypes are valuable. Moving fast is valuable. The goal is to build prototypes that are easier to either throw away or graduate.

One approach that works well: treat your validation-phase code like a science experiment, not a product. Document the assumptions explicitly, in comments or in a companion doc. What are you trying to learn? What corners are you cutting on purpose? What would need to be true for this to become real infrastructure?

When the prototype survives, you have a written record of every shortcut you took. That's your rewrite spec. It tells you exactly what debt you accumulated and why.

Another approach: build a hard boundary around the prototype from day one. Give it a clear API surface, even if the internals are a mess. When the time comes to replace it, you're swapping out a module, not untangling a web.

The Tax Collector Always Comes

The prototype tax doesn't forgive and it doesn't forget. It just waits. It waits until you're trying to scale, until you're onboarding a new team, until a customer asks for a feature that would require touching the one part of the system nobody wants to touch.

The teams that come out ahead aren't the ones who never wrote prototype code. They're the ones who were honest about what they were doing, kept records of the decisions they made under pressure, and had a plan — even a rough one — for what graduation or retirement would look like.

Shipping fast is the point. But knowing what you shipped, and what it cost you, is what keeps you shipping fast a year from now.

All Articles

Related Articles

Silent Failures: The Async Work Your System Forgot It Was Doing

Silent Failures: The Async Work Your System Forgot It Was Doing

Your GitHub Profile Is the New Business Card Nobody Told You About

Your GitHub Profile Is the New Business Card Nobody Told You About

Deploy on a Tuesday Afternoon and Go Home Calm: The Feature Flag Mindset

Deploy on a Tuesday Afternoon and Go Home Calm: The Feature Flag Mindset