The Problem
Your prototype works. Now someone asks: "Can we ship this?" And you freeze.
The code is held together with hope and TODO comments. Shipping feels irresponsible. But rewriting from scratch feels wasteful. You're not sure how to evaluate what you have.
The real question isn't "prototype or production." It's: What parts of this prototype can survive contact with production?
The Core Insight
Not all code needs the same treatment. A prototype has three types of code:
| Category | Description | Action |
|---|---|---|
| Keep | Works correctly, handles edge cases, readable | Ship as-is with minor cleanup |
| Harden | Logic is sound, but needs error handling, tests, or documentation | Add production qualities |
| Rewrite | Fundamentally flawed - wrong approach, security issues, technical debt | Start fresh with lessons learned |
The framework helps you categorize each piece of code and make deliberate decisions.
The loop that does this
Run the triage below by hand the first time, on a project you actually care about. Not because the manual pass is better — it isn't — but because the scoring has two places it quietly goes wrong, and if you have never watched those places yourself you will take a confident green verdict at face value.
After that it should be one instruction, not an afternoon: "Go through my project piece by piece. For each, tell me what breaks if it fails, how solid the code is, and whether it's keep, harden, or rewrite — with a file and line behind every call." Save it where your agent will find it again — a skill if yours installs them, otherwise the instructions file it reads each session. A verdict with no line number behind it is a guess. The two calls that stay yours: how much a failure would really cost you, and whether you can live with the risk you're choosing to keep.
The Decision Framework
Step 1: Risk Assessment
For each component, ask: What happens if this breaks in production?
Risk Levels
- Low Risk: Users see an error, retry, life goes on (UI glitches, non-critical features)
- Medium Risk: Users lose work or have degraded experience (data display, notifications)
- High Risk: Data loss, security breach, financial impact (auth, payments, data storage)
High-risk code needs hardening or rewrite. Low-risk code might ship as-is.
Step 2: Code Quality Audit
For each component, evaluate:
| Criterion | Prototype Level | Production Level |
|---|---|---|
| Error Handling | Crashes or silent failures | Graceful degradation, user feedback |
| Input Validation | Assumes valid input | Validates and sanitizes all input |
| Edge Cases | Happy path only | Handles nulls, empty, boundaries |
| Tests | None or minimal | Critical paths covered |
| Documentation | Code comments, maybe | API docs, README for maintainers |
| Logging | console.log statements | Logs with a consistent, searchable shape (known as structured logging), plus error tracking |
Step 3: The Decision Matrix
Combine risk level with quality score:
Low Quality Medium Quality High Quality
High Risk REWRITE HARDEN KEEP (review)
Medium Risk HARDEN HARDEN/KEEP KEEP
Low Risk KEEP (maybe) KEEP KEEP
Applying the Framework
Example: E-commerce Checkout Prototype
Let's categorize a prototype checkout flow:
Component: Cart Display
Risk: Low (wrong display, user notices, retries)
Quality: Medium (works, no edge case handling)
Decision: KEEP - add basic null checks
Component: Payment Processing
Risk: High (money involved, security critical)
Quality: Low (happy path only, no validation)
Decision: REWRITE - use established payment library
Component: Order Confirmation Email
Risk: Medium (missed emails = support tickets)
Quality: Medium (works, no retry logic)
Decision: HARDEN - add retry logic and logging
Hardening Checklist
When a component needs hardening (not rewrite), here's what to add:
Minimum Viable Production (MVP)
Startups have a name for the smallest version that can prove an idea: it's called a minimum viable product - and in the shorthand everyone actually uses, it's the MVP. Hardening has the same floor:
- Input validation - Validate types, ranges, required fields
- Error handling - Try/catch with meaningful error messages
- Null checks - Handle missing data gracefully
- One test - At least one test for the critical path
- Logging - Log errors with enough context to debug
Full Production
Add to MVP:
- Edge case tests - Empty arrays, null values, boundary conditions
- Documentation - Function signatures, expected behavior
- Metrics - Track usage, errors, performance
- Rate limiting - Prevent abuse (if applicable)
- Graceful degradation - Fallbacks when dependencies fail
Rewrite Triggers
When should you rewrite instead of harden?
Rewrite If:
- Security flaw is fundamental - e.g., storing passwords in plain text
- Architecture is wrong - e.g., polling when you need WebSockets
- Technical debt exceeds value - hardening would take longer than rewriting
- Performance is structurally bad - the work grows much faster than the data does; engineers call this time complexity, and write it in a notation called O(n) - e.g., O(n²) when O(n) is possible
- You don't understand it - if you can't explain it, you can't maintain it
The Sunk Cost Trap
"But I spent 3 hours on this!"
Doesn't matter. Those hours are gone whether you keep the code or not, and letting them steer the decision has a name: sunk cost. The question is: Will hardening this take more or less time than rewriting?
Rule of thumb: If hardening a component would take more than 2x the time to rewrite it properly, rewrite.
Technical Debt Assessment
Every shortcut you took to get the prototype working is a cost you deferred, not one you dodged - engineers call this technical debt. Every prototype accumulates it; categorize it:
| Debt Type | Example | Urgency |
|---|---|---|
| Deliberate Debt | "We'll add caching later" | Scheduled |
| Accidental Debt | Discovered edge case bug | Before ship |
| Bit Rot | Deprecated dependency | Soon |
| Reckless Debt | "We'll figure it out" | Now (or never) |
Reckless debt is the killer. If you shipped code without understanding it, you're going to pay interest forever.
Failure Patterns
1. The Perfectionist Trap
Symptom: Nothing ever ships because nothing is "production ready."
Fix: Define "good enough" before you start hardening. Hit that bar and ship.
2. The Ship-and-Pray
Symptom: Everything ships as prototype. Production is constant firefighting.
Fix: Use the risk matrix. At minimum, harden high-risk components.
3. The Rewrite Addiction
Symptom: "This would be better if we just started over" - said repeatedly.
Fix: Rewrites must be justified. If you can't quantify why hardening won't work, don't rewrite.
Quick Reference
The 5-Minute Assessment:
- List all components/modules
- Rate each: High/Medium/Low risk
- Rate each: High/Medium/Low quality
- Apply matrix: Keep/Harden/Rewrite
- Estimate time for Harden/Rewrite items
Hardening Priorities:
- Security (auth, input validation)
- Data integrity (storage, processing)
- Error handling (user-facing errors)
- Logging (production debugging)
- Tests (preventing regressions)
Rewrite Threshold: If hardening takes >2x rewrite time, rewrite.