Why “Almost Done” Work Breaks Development Flow

Every team has it.

A pull request that’s “basically finished.”
A feature that’s “just missing a few small things.”
A task marked as almost done for the third week in a row.

It rarely looks like a problem. There’s no failing build, no red alerts, no production outage. And yet, this kind of work is one of the most effective ways to quietly destroy development flow.

Not by being wrong — but by never being truly finished.

Previous article in this category: https://codecraftdiary.com/2026/01/10/effective-code-reviews/


In theory, almost done sounds harmless. In practice, it usually means one or more of the following:

  • Tests are missing or incomplete
  • Edge cases are known but postponed
  • Naming or API design “can be improved later”
  • Migration exists, rollback does not
  • Documentation is optional… for now

None of these issues are dramatic on their own. That’s why they survive. The problem is that almost done work doesn’t behave like work in progress — it behaves like invisible technical inventory.

It sits in the system.
It consumes attention.
And it blocks flow.


Half-finished work creates a powerful illusion: movement without completion.

From the outside, things look active:

  • PRs are open
  • Commits keep coming
  • Sprint boards show progress

But internally, the system is stuck.

Developers context-switch back to old code.
Reviewers repeatedly re-load the same mental model.
Small unresolved decisions accumulate into cognitive debt.

Nothing moves forward cleanly, because nothing is allowed to end.


A task that hasn’t been started yet is cheap.

A task that’s almost done is expensive.

Why?

Because almost done work demands continuous re-entry. Every return requires:

  • Rebuilding context
  • Re-evaluating past decisions
  • Re-answering questions that should have been resolved once

This is not linear cost — it compounds.

The longer work stays in this state, the more expensive finishing it becomes. At some point, teams stop finishing at all. They work around it instead.

That’s when flow collapses.


Code reviews amplify this problem dramatically.

A PR that’s nearly ready but not quite there:

  • Gets reviewed
  • Receives feedback
  • Gets partially updated
  • Then stalls

When it comes back days later, the reviewer must start over.

Multiply that by several PRs and several developers, and you get review fatigue — not because reviews are bad, but because they never conclude.

At that point, reviewers stop caring about quality and focus on getting it merged. Standards drop, resentment grows, and nobody can quite explain why.

One of the most visible symptoms of almost done work is a pull request that sits open for too long.

At first, nothing seems wrong. The code is there. CI is green. Review is “scheduled.”
Then time passes.

While the PR waits, the main branch moves on:

  • New features are merged
  • Refactors happen elsewhere
  • Dependencies shift subtly

When the original author finally comes back, the PR is no longer just waiting for approval — it’s out of date.

Imagine a backend pull request that introduces a new endpoint.

The logic is implemented. Tests exist, but only for the happy path.
The author opens the PR and asks for review.

The review doesn’t happen that day.

Two days later, another feature touches the same service.
A small refactor is merged. Nothing dramatic.

When the original PR finally gets reviewed, it now has conflicts.
Tests fail because assumptions changed. The reviewer’s comments are no longer fully relevant.

What was a one-hour review becomes a half-day cleanup.

Nothing about the code was wrong.
It just waited long enough for the system to move around it.

That’s the real cost of “basically finished” work.


At this point, conflicts appear. And teams often treat them as a tooling issue.

They are not.

Merge conflicts are a process failure.

They happen because work was allowed to remain unfinished long enough for the system around it to change. The longer a PR stays open, the higher the probability that it collides with unrelated changes.

This creates a feedback loop:

  • PR waits for review
  • Branch diverges
  • Conflicts appear
  • Author postpones fixing them
  • Review is delayed again

The PR becomes heavier every day it remains open.


Long-lived PRs don’t just create technical conflicts — they create psychological resistance.

Developers start associating the PR with:

  • Painful rebases
  • Repeated test failures
  • Comments they’ve already addressed once

So they avoid it.

“This will take a full afternoon.”
“I’ll deal with it when I have time.”

That avoidance keeps the work in the almost done state even longer — exactly where it does the most damage.


Teams often blame developers for not finishing work.

But in many cases, the real issue is review latency.

If reviews routinely take days:

  • Developers stop prioritizing clean completion
  • PR size increases (“If it takes days anyway…”)
  • Conflicts become normal, not exceptional

At that point, the workflow trains people to leave things unfinished.


The solution is not hero reviewers or stricter rules. It’s shorter lifetimes.

A PR that:

  • Is reviewed within hours
  • Merged the same day
  • Or explicitly rejected early

…does not accumulate conflicts, fatigue, or resentment.

It either finishes — or it dies quickly.

Both outcomes preserve flow.


One simple but effective practice is to treat waiting PRs as first-class problems.

For example:

  • Highlight PRs open longer than 48 hours
  • Treat “waiting for review” as a blocker, not a state
  • Prefer reviewing over starting new work

When waiting becomes visible, it stops being normal.


Conflicts, rebases, and stalled PRs are not isolated issues.

They are downstream effects of allowing work to stay almost done.

If you want fewer conflicts, don’t fight Git.
Finish work faster — or stop starting it.


In Lean thinking, unfinished work is called inventory.

Inventory is dangerous because:

  • It hides problems
  • It ties up resources
  • It creates false confidence

Software teams rarely think in these terms, but the parallel is exact.

Half-finished features are inventory.
Open PRs are inventory.
“Almost done” tasks are inventory.

And like any excess inventory, they slow the entire system.


The most dangerous causes are the ones that feel justified:

1. Large Pull Requests

“Let’s do it properly in one go.”

Large PRs increase the chance that something remains unresolved — and once they stall, they tend to stay stalled.

2. Vague Definition of Done

If done isn’t explicit, almost done becomes acceptable.

Without a shared baseline (tests, docs, rollback, review passed), everyone uses their own internal standard.

3. Deferred Decisions

“We’ll clean this up later.”
“Let’s just ship it first.”

Later rarely comes.


Backend work has properties that make almost done especially toxic:

  • Hidden coupling between systems
  • Migrations that can’t be half-applied
  • APIs that lock in contracts early
  • Bugs that surface weeks later

A frontend workaround might be ugly but visible.
A backend shortcut is often invisible — until it explodes.

That’s why backend teams feel “slow” even when they work constantly.

They’re not slow. They’re stuck finishing yesterday’s almost-done work.


This is not about discipline or motivation. It’s about system design.

1. Define “Done” Ruthlessly

If it’s merged, it must include:

  • Tests
  • Review approval
  • Clear naming
  • Migration safety (if applicable)

Anything else is not done.

2. Reduce PR Size

Smaller PRs:

  • Finish faster
  • Get reviewed faster
  • Fail faster

They either complete — or get killed early.

3. Ban “Almost Done” Language

This sounds extreme, but language shapes behavior.

Replace:

“It’s almost done”

With:

“It’s blocked because X”

Blocked work is honest. Almost done is deceptive.

4. Prefer Completion Over Throughput

Shipping fewer things that actually finish beats starting many things that don’t.

Flow comes from completion, not activity.


Many teams optimize for starting work.
Few optimize for finishing it.

Finishing requires:

  • Making decisions uncomfortable early
  • Accepting “good enough” instead of perfect
  • Closing loops deliberately

It feels slower at first.
Then everything accelerates.


Development flow isn’t created by speed, tools, or frameworks.

It’s created by ending things cleanly.

If your team feels busy but stuck, don’t ask how to move faster.
Ask how much work is almost done — and why it’s allowed to stay that way.

Because unfinished work doesn’t just wait.

It actively slows everything around it.


Leave a Reply

Your email address will not be published. Required fields are marked *