Why I Delete Most of My Code Before Committing
The best code I write never makes it to production. Here's why that's exactly how it should be.
The Confession
I deleted 847 lines of code yesterday. Perfectly working code. Code that passed all tests, handled edge cases elegantly, and would have impressed anyone in a code review.
Then I replaced it with 23 lines.
This wasn't refactoring gone wild. It's how I've worked for years, and it's made me a dramatically better engineer. Most developers treat deletion as failure — I treat it as the goal.
The Throwaway Draft Technique
Here's my dirty secret: my first implementation is always intentionally disposable.
I don't mean "rough around the edges." I mean I write it knowing I'll delete it. The first version exists purely to help me understand the problem.
Last month, we were building a real-time collaboration feature for a client's document editor. My first pass looked like this:
// First attempt: 400+ lines of WebSocket management,
// conflict resolution, and state synchronization
class CollaborationManager {
private socket: WebSocket;
private documentState: Map<string, any>;
private pendingOperations: Queue<Operation>;
private conflictResolver: ConflictResolver;
// ... 15 more private fields
constructor(config: CollaborationConfig) {
// 50 lines of initialization
}
// 20+ methods averaging 30 lines each
}
It worked. It handled disconnections, resolved conflicts, maintained consistency. I was proud of it.
Then I deleted it.
What Deletion Taught Me
Writing that first version revealed something crucial: 80% of my "conflict resolution" was solving problems that couldn't actually occur given our document structure.
The final implementation:
function useCollaboration(documentId: string) {
const channel = useSupabaseChannel(`doc:${documentId}`);
const broadcast = useCallback((operation: Operation) => {
channel.send({ type: 'operation', payload: operation });
}, [channel]);
useEffect(() => {
return channel.on('operation', applyOperation);
}, [channel]);
return { broadcast };
}
Twenty-three lines. Same functionality. Why? Because my throwaway code revealed:
- Supabase Realtime already handled reconnection
- Our CRDT-based document model made conflicts mathematically impossible
- The state management I'd built duplicated what React already provided
I couldn't have seen this without writing the complex version first.
The Cognitive Trick
There's a psychological principle at work here: premature optimization of understanding.
When we sit down to solve a problem, we immediately start optimizing. We think about edge cases before we understand the happy path. We architect for scale before we know what we're scaling.
Writing throwaway code is permission to be naive. To ask "what if I just did the dumbest possible thing?" without the voice in your head screaming about technical debt.
How to Practice Intentional Deletion
Rule 1: Set a Deletion Deadline
Before writing anything, I decide: "This code dies in 2 hours." No exceptions. Even if it's beautiful. Even if it works.
This constraint is liberating. I don't worry about naming conventions. I hardcode values. I copy-paste shamelessly. The goal is understanding, not craftsmanship.
Rule 2: Write the Retrospective First
After deleting, before rewriting, I spend 10 minutes answering:
- What did I assume that was wrong?
- What was harder than expected?
- What was easier than expected?
- What would I tell past-me before starting?
This reflection is where the real learning happens.
Rule 3: The Second Version Must Be Uncomfortable
If your rewrite feels natural and obvious, you didn't learn enough from the first version. The second version should make you slightly uncomfortable — it should feel too simple, too naive, too easy.
That discomfort means you've actually found the essence of the problem.
When This Doesn't Work
I'll be honest about the trade-offs:
Time pressure kills this approach. When a client needs something shipped yesterday, you can't afford throwaway code. But here's the thing — after years of practicing intentional deletion, my "first attempt" instincts have gotten dramatically better. The practice pays forward.
Team coordination gets tricky. If you're pair programming or working in rapid PR cycles, deleting 800 lines looks like you wasted everyone's time. I solve this by doing throwaway work solo, often outside normal hours.
It requires ego management. Deleting working code feels like admitting failure. It's not. It's admitting that learning happened.
The Weird Productivity Math
Here's where it gets counterintuitive:
I ship faster by writing more code that I delete.
Our last three client projects at Ember Studios averaged 40% less time-to-completion than our historical baseline. Not because we're coding faster — because we're deleting faster.
Every hour spent on throwaway code saves three hours of debugging, refactoring, and meetings about "why is this so complicated?"
The Challenge
Next time you face a non-trivial problem, try this:
- Write the worst possible solution that technically works
- Delete it entirely — not refactor, delete
- Wait 30 minutes
- Write it again from scratch
The second version will be better. Not because you're a better programmer, but because you're solving a problem you actually understand.
The best code isn't the code that survives. It's the code that teaches you what to write next.
Stop optimizing your first draft. Start optimizing your understanding. The code will follow.
