Fifteen years of writing code and I still mass-delete my first draft
The first draft reveals the problem's shape. The second draft solves it. Engineers who try to write perfect code on the first pass are optimizing for the wrong thing.
Last Tuesday I spent four hours building a transaction matching algorithm for a new reconciliation edge case. The code worked. The tests passed. The approach was clean enough. Then I selected the entire file and deleted it.
I rewrote it in ninety minutes. The second version was half the size, handled two edge cases the first version missed, and used a data structure that made the performance characteristics obvious. The first version was a draft. The second version was the solution.
This is how I have worked for fifteen years. I am not sure I could work any other way.
Most of the leadership posts in this phase are me compressing scar tissue into defaults. It also builds on what I learned earlier in “Why your engineering strategy document is probably a wish list, not a strategy.” I am less interested in performative management language now and more interested in the boring mechanisms that keep teams aligned when nobody is in a heroic mood.
Why the First Draft Exists
The first draft is not meant to ship. It is meant to reveal the problem. Before you write code, you think you understand the problem. You have read the ticket. You have sketched an approach. You have a mental model. The first draft proves whether that mental model is correct.
It usually is not. The first draft always teaches me something I did not know before I started coding. An edge case I had not considered. A data relationship I had simplified in my head. A performance constraint that only becomes visible when you see the actual data flow. These discoveries are the point of the first draft. They are not failures. They are the draft doing its job.
The mistake engineers make is treating the first draft as something to fix instead of something to replace. You see a problem in your first pass, so you patch it. Then you patch the patch. Then you refactor the patched patch. By the end, you have a solution built on top of a mental model you know is wrong, held together by fixes for a model you have already outgrown.
The Delete-and-Rewrite Pattern
My workflow has not changed in a decade:
- Write the first draft quickly. Do not optimize. Do not refactor as you go. Get something working that proves the approach is viable.
- Write tests for the first draft. Not comprehensive tests. Just enough to verify the core behavior is correct.
- Study the first draft. What did I learn that I did not know before? What would I do differently? Where did the code get complicated, and is that complexity essential or accidental?
- Delete the first draft. All of it. Not refactor. Delete.
- Write the second draft from scratch, incorporating everything the first draft taught me. The second draft usually takes a third of the time because I now understand the problem.
The key insight is that the rewrite is faster than incremental refactoring. Refactoring a bad mental model into a good one is like renovating a house with a bad foundation. You can do it, but it takes longer than building a new house on a good foundation.
Why This Scares Junior Engineers
When junior engineers see me delete four hours of work, they react with visible discomfort. Four hours wasted. That is how it looks from the outside. From the inside, nothing was wasted. The four hours bought me understanding that I could not have gotten any other way.
I tell them: the first draft’s job is to make the second draft possible. You are not throwing away work. You are trading a rough prototype for precise understanding. That trade is always worth it.
The engineers who struggle most with this pattern are the ones who have been praised for writing clean code on the first attempt. They have optimized for appearing efficient. They write carefully, refactor as they go, and produce code that looks polished but encodes whatever incomplete understanding they had when they started. The code is neat. The approach is often wrong in ways that neat code hides.
When to Not Delete
This pattern is not universal. I do not delete and rewrite when:
- The first draft is a known pattern executed on a well-understood problem. CRUD endpoints do not need a discovery draft.
- The first draft is on a critical path with a tight deadline and the approach is correct even if the implementation is messy. Sometimes good enough on time beats perfect late.
- The team has already reviewed and approved an approach. Deleting after approval wastes their review effort. In this case, refactoring is the right move.
But for anything novel, complex, or architecturally significant, the delete-and-rewrite pattern is my default. It is faster, it produces better code, and it forces me to confront what I do not understand instead of papering over it.
The Meta-Lesson
This is the phase where individual scars finally turned into repeatable operating principles. I cared less about sounding clever and more about leaving behind a system that stayed sane without me in the room. That is how I build portfolio, pipeline-sdk, and dotfiles too.
Expertise is not the ability to get it right on the first try. Expertise is the ability to recognize what is wrong with the first try and fix it quickly. Speed comes from fast iteration, not from careful first attempts.
Fifteen years in, my first drafts are not better than they were five years ago. They are still messy, incomplete, and wrong in predictable ways. What has improved is my ability to extract understanding from them and my willingness to throw them away. The craft is not in the writing. It is in the rewriting.