# Shipping Beats Perfect: A Manifesto for Pragmatic Developers
By Govind Bajaj · 2025

Tags: productivity, shipping, opinion, career, manifesto
I have never regretted shipping imperfect code. I have regretted not shipping at least a dozen times. Perfect is the enemy of deployed. Here's the pragmatic developer's manifesto.
I have never regretted shipping imperfect code.

I have regretted not shipping at least a dozen times. Features that sat in development for months while competitors launched. Refactors that never ended because there was always one more improvement. Products that died in development because they were never quite ready.

Perfect is the enemy of deployed. Here is the pragmatic developer's manifesto.

## Principle 1: Working Software Is the Primary Measure of Progress

This is from the Agile Manifesto and it is still true. A working feature with known limitations is infinitely more valuable than a perfect feature that does not exist.

The Sans Herbals checkout had a bug where the coupon code field did not validate on the client side. Server-side validation caught it. I shipped it anyway. Two thousand orders processed successfully while I fixed the client-side validation in the next release.

## Principle 2: Done Is Better Than Perfect

Done means: it works for the primary use case, it handles the common edge cases, it has tests for critical paths, and it is documented enough that someone else can maintain it.

Done does not mean: it handles every edge case, it is fully documented, it has one hundred percent test coverage, and the code is beautiful.

The gap between done and perfect is where projects go to die.

## Principle 3: Technical Debt Is a Tool, Not a Sin

Technical debt is borrowing time from the future to ship today. Like financial debt, it is useful when used intentionally and dangerous when accumulated unconsciously.

I intentionally take technical debt when: the feature is time-sensitive (competitor is launching), the market is unproven (might pivot), or the manual process works for now (ten users, not ten thousand).

I pay down technical debt when: the manual process no longer scales, the debt is blocking other features, or the risk of failure exceeds the cost of refactoring.

## Principle 4: Refactor in Production, Not in Development

The best time to refactor is when you have real usage data. Refactoring a component before launch is guessing at the right abstraction. Refactoring it after seeing how users actually interact with it is informed by evidence.

The Royal Madrasi order management system was refactored three times in its first year. Each refactor was informed by real usage patterns, not theoretical concerns. The current version looks nothing like the original — and it is better because of it.

## Principle 5: The User Does Not See Your Code

Users see the output of your code. They see fast load times, smooth interactions, and features that solve their problems. They do not see whether you used the repository pattern or clean architecture.

Optimize for user experience first. Code quality serves the user by enabling speed and reliability. It is not an end in itself.

## The Pragmatic Checklist

Before shipping, ask: Does it work for the primary use case? Are the critical paths tested? Can it handle the expected load? Can I fix it quickly if it breaks?

If the answer to all four is yes, ship it.

## Takeaways

- Working software is the only measure of progress that matters
- Done is better than perfect — the gap between them kills projects
- Technical debt is a tool — use it intentionally, pay it down strategically
- Refactor based on real usage data, not theoretical concerns
- Users see the output of your code, not the code itself
- Ship when critical paths work and you can fix quickly — polish comes later
- I have never regretted shipping imperfect code, but I have regretted not shipping at least a dozen times
- The pragmatic developer ships, learns, and improves — the perfectionist never ships