ShipAnyways ← All posts

Ship Before You Refactor

You've built something that works and users need it. But you're polishing internals they can't see, and the ship date is slipping. Rough code that ships beats perfect code that doesn't.

Ship Before You Refactor

You've shipped before. You know it matters. But this project feels different. The code works, but you can see it could be better structured, and you're back in the editor "just fixing one thing."

Three hours later, you still have not shipped.

The issue is not perfectionism. Perfectionists are at peace with their work. This is something else: the belief that refactoring before shipping is the same cost as refactoring after. It sounds reasonable. It costs you the ship date.

Here is what happens next: You refactor one thing, and it reveals three more things that should be refactored too. Then the "quick fix" becomes the entire evening. Users who needed this feature yesterday never get it because you are polishing the internals they cannot see.

You're in the refactoring trap

The trap has a logic that feels airtight. You have built something that solves a real problem. Users would benefit from it today. But because you can see the path to "better," you have convinced yourself that shipping now means shipping a mess.

It does not. It means shipping progress.

The thing is, you will refactor this after shipping anyway. So why not refactor now? The reason: refactoring before shipping costs time. Refactoring after shipping costs guilt. Guilt feels lighter, so you choose it. Then the project ships six weeks late.

Ship-critical vs ship-nice: the decision

There are only two kinds of problems with code.

Ship-critical problems break behavior, corrupt data, or expose security issues. They must be fixed before shipping. Full stop.

Ship-nice problems are everything else: structure, naming, duplication, style, efficiency, elegance. They make the code better to work with after shipping. They do not make the shipped feature work differently.

The mistake is treating them as the same problem. You have not shipped yet, so you assume combining the fix with the refactoring is free. It is not. Every minute refactoring is a minute not shipping.

Here is the decision that breaks the trap: Fix ship-critical problems. Ship. Add ship-nice improvements to the backlog. Refactor them when the project is live and generating value.

The ship date as a forcing function

A ship date is not a deadline. It is a decision. And decisions force choices you would not otherwise make.

Without a ship date, refactoring is infinite. You can always see one more thing to improve. The structure is not quite right. The edge cases are not handled elegantly.

With a ship date, you have a single question: Does this ship-block the feature? If no, it ships. If yes, fix it.

A forcing function is not cruel. It is the only thing that stops you from polishing the same piece of work forever.

Set the date. Announce it. Let it narrow your focus.

Refactoring belongs in the next cycle

After you ship, you have three options:

1. Keep building new features on the rough code. 2. Spend time refactoring what you just shipped. 3. Do both: refactor in parallel while building the next thing.

Option 1 is common and leads to technical debt. Option 2 is tempting and leads to slow shipping. Option 3 takes discipline but pays off.

Here is what it looks like: You ship the feature on Monday. Tuesday, you start a new feature branch. Meanwhile, on a separate branch, the refactoring work happens. Both move in parallel. Neither blocks the other.

When refactoring is complete, you merge it back into main. New features continue. You shipped on time. You get cleaner code. And you do not make users wait for polish they did not ask for.

Real projects that shipped rough first

Rough code that ships and gets refactored later is not an edge case. It is the standard outcome of builders who actually ship things. The code works. Users get value. Structure improves incrementally.

The projects that suffer are the ones that prioritize refactoring before shipping. They take longer. They miss windows of opportunity. They lose the chance to learn from real usage and adjust course.

When you ship rough, you get real feedback. That feedback often changes what you thought needed refactoring. So the refactoring you prevented was not just a delay. It was work that would have been wasted anyway.

FAQ

Won't you end up rewriting the code later anyway?

Refactoring is not rewriting. Refactoring changes structure while keeping behavior the same. Rewriting is throwing it out and starting over, which is a total loss. Rough code refactors cleanly most of the time. You fix the style, improve the structure, rename things for clarity, eliminate duplication. The cost is lower than delaying shipping.

How do you get team or stakeholder buy-in for shipping rough code?

Separate the decision into two questions. First: Does this feature work correctly and does it solve the problem? If yes, it is shippable. Second: Does this need refactoring before we build the next thing? If yes, add it to the backlog. These are not one decision. They are two. Most friction happens when someone conflates them. The conversation becomes, "We can't ship this because the code is rough." The reframe is, "We can ship this because it works. The refactoring goes to the next cycle." Frame it as structure and priority, not risk. The risk is letting rough code block users from value.


Ship Anyways is a channel of Round Table Strategy LLC, written and published by Regie Durana. Ship Anyways is a trademark of Round Table Strategy LLC. © 2026. All rights reserved.