SoftLinkers All articles
Engineering Best Practices

Nobody Can Agree on When You're Actually Done — and That's Tanking Your Releases

SoftLinkers
Nobody Can Agree on When You're Actually Done — and That's Tanking Your Releases

You've been in this meeting. The feature is built. Tests are passing. The PR got merged three days ago. And somehow, someway, you're still talking about it.

Someone wants to tweak the copy. Someone else noticed an edge case in a browser nobody on the team actually uses. A stakeholder saw a competitor's version and now wants "just a small adjustment" to the layout. And suddenly, a feature that was supposed to ship Tuesday is still sitting in staging two weeks later.

This isn't a motivation problem. It's not a people problem. It's a definition problem — and it's one of the quietest, most expensive dysfunctions in software development.

The Finish Line That Keeps Running Away From You

Here's the uncomfortable truth: most engineering teams don't have a real definition of done. They have a feeling of done. And feelings are terrible acceptance criteria.

When done is a vibe, every stakeholder gets to have a different one. The PM thinks done means the happy path works. The designer thinks done means it looks right on their MacBook Pro. The QA engineer thinks done means every edge case is documented. The backend dev thinks done means the API is returning 200s. None of them are wrong — but none of them are aligned, either.

That misalignment doesn't just slow things down. It quietly erodes trust across the team. Engineers start to feel like their work is never actually valued because it's never actually finished. PMs get frustrated that timelines keep slipping. Leadership wonders why the team struggles to ship consistently. Everyone's working hard, and nobody's making progress.

When "Polish" Becomes a Trojan Horse

Scope creep has a reputation for being obvious — the stakeholder who wants to add a whole new feature mid-sprint, the last-minute pivot after a demo. But the more insidious version is the kind dressed up as polish.

Polish sounds responsible. It sounds like craftsmanship. Nobody wants to be the person who argues against quality. So when someone says "it just needs a little more polish before we ship," the team nods along. And then it happens again next sprint. And the one after that.

The problem is that polish without a scope is infinite. There is always something that could be smoother, faster, prettier, or more forgiving of user error. That's not a flaw in your team — that's just the nature of software. The question isn't whether improvements are possible. The question is whether they're necessary for this version to ship.

When your team can't answer that question with a clear yes or no, polish becomes a holding pattern that costs real sprint velocity and real engineering hours — while delivering nothing to users.

Vague Acceptance Criteria Are Doing More Damage Than You Think

Let's talk about tickets. Specifically, let's talk about acceptance criteria that say things like "the UI should feel intuitive" or "performance should be acceptable" or — the classic — "it should work like the old system."

These aren't acceptance criteria. They're wishes. And when you build a sprint around wishes, you get exactly the kind of ambiguity that turns a two-week feature into a six-week argument.

Good acceptance criteria are specific, testable, and agreed upon before development starts — not after a demo reveals that two people had completely different mental models of what was being built. They define what success looks like in concrete terms: which user actions must succeed, what error states are in scope, what performance threshold is acceptable, and — critically — what is explicitly out of scope for this version.

That last part is the piece most teams skip. Defining what you're not building is just as important as defining what you are. It gives your team permission to say "that's a great idea, let's put it in the backlog" instead of "sure, we can add that" for the fourteenth time.

Building a Definition of Done That Actually Sticks

So what does a real, defensible definition of done look like? It depends on your team and your product, but here's a framework worth building from.

Done means the acceptance criteria are met. Not mostly met. Not met except for that one edge case. Met. If the criteria weren't written clearly enough to make this determination, that's a process failure to fix before the next sprint — not a reason to keep the ticket open.

Done means it's been reviewed by the right people. This is not the same as reviewed by everyone. Define who has sign-off authority for what. A design review shouldn't require the CTO. A security review shouldn't be optional for auth changes. Get specific about who needs to look at what.

Done means it's deployable. Not "ready for staging." Not "almost ready for production." If it can't go to production today, it's not done. This is a harder standard than most teams hold themselves to, but it's the one that actually prevents the endless limbo of features that are "done" but somehow never ship.

Done means the next person can maintain it. Documentation, tests, and observable logging aren't gold-plating — they're the minimum bar for handing off work that won't become someone else's emergency at 2am six months from now.

Making the Conversation Happen Before It's Too Late

The real work here isn't technical. It's relational. Getting your team aligned on a definition of done means having conversations that feel uncomfortable — conversations about authority, about priorities, and about what "good enough" actually means for your product at this stage.

That conversation is easier to have at sprint planning than it is in a post-mortem after a release slipped by three weeks. Build the habit of asking, before any ticket moves into development: what does done look like, who decides when we're there, and what are we explicitly not doing in this version?

Write the answers down. Put them in the ticket. Reference them when the scope starts to drift.

It won't be a perfect system on the first try. But a written, visible, agreed-upon definition of done is something your team can improve. A vague, shifting, emotional finish line is something you can only survive — until you can't.

Ship the thing. Then make it better. That's not cutting corners. That's how software actually works.

All Articles

Related Articles

Code Review Is Supposed to Make Things Better. Here's Why It's Making Things Worse.

Code Review Is Supposed to Make Things Better. Here's Why It's Making Things Worse.

Drowning in Channels: How Your Communication Stack Became the Bottleneck

Drowning in Channels: How Your Communication Stack Became the Bottleneck

Your Git Log Is a Graveyard: How to Turn Version Control Into Actual Team Memory

Your Git Log Is a Graveyard: How to Turn Version Control Into Actual Team Memory