DEV Community

Cover image for The DoD Experiment: Trying to Fix ‘Done’ Before It Breaks Us
Balthazar de Moncuit
Balthazar de Moncuit

Posted on

The DoD Experiment: Trying to Fix ‘Done’ Before It Breaks Us

This is the first in a series documenting an experiment: bringing clarity and explicit agreements to a distributed engineering team. Starting with something deceptively simple—the Definition of Done.


I've been putting off writing about my work for years. The excuse was always the same: "I'll write once I've figured it out."

Which is bullshit, obviously. You never figure it out. You just accumulate scar tissue and call it experience.

The truth is simpler: I was waiting to have a success story worth telling. Because who wants to read "here's what I'm trying, it might crash"?

Turns out, that's exactly what's interesting. The messy middle where you don't know if your hypothesis is brilliant or stupid.

So here we go. I'm a frontend lead at a Swiss healthcare company, and I'm about to try something that will either improve how we work or confirm that I've been solving the wrong problem for months.

Place your bets.

Last month, we shipped a fairly standard feature

Straightforward on paper: some UI, some interactions, some integration points.

Estimation: 3 days.

Reality: 9 days.

The search for answers

I spent evenings reading the GitLab handbook. Procrastination disguised as professional development.

I fell in love with it. The async-first culture. Everything written down. Everything accessible. No one's productivity held hostage by someone else's calendar.

My first thought: "We should do this. Better Confluence structure. Better Teams channels. Clear async workflows."

I started sketching out the infrastructure. How we'd organize channels. What notifications would go where. How documentation would flow.

Then it hit me: I was designing the plumbing for a house with no foundation.

The culture problem

GitLab's async-first approach doesn't work because of their tools. It works because of their culture.

But what is that culture, exactly?

Trust? Sure, but trust in what?

Shared understanding? Getting closer.

The ability to read something once and know what's expected? That's it.

When everyone agrees on what "complete" means, you don't need meetings to clarify. When systems are documented, you don't need to interrupt someone to understand them. When definitions are explicit, you don't need to negotiate scope on every ticket.

The async infrastructure is the result, not the cause.

What was under my nose the whole time

During sprint reviews, developers had been pointing it out: "We don't have a Definition of Done."

Not as an accusation. As an observation. A problem they saw but couldn't fix themselves.

Basic stuff. In every agile textbook. Some of my developers were actively advocating for it.

And I'd been nodding along, thinking "yeah, we should have that," while not realizing the obvious: as the lead, bootstrapping that Definition of Done is my job. Not Product's job to define. Not the team's job to spontaneously create. Mine to initiate.

I needed it to come from GitLab—from somewhere that felt authoritative—to actually understand what I was looking at.

Slow learner. Or maybe just immune to anything that doesn't come wrapped in a 300-page handbook from a company I admire from a distance.

The hidden cost of implicit contracts

We work on implicit contracts.

I expect tests. You expect tests only for critical paths. Another developer expects tests only when explicitly requested.

I expect error handling following a specific pattern. You don't know that pattern exists.

I expect documentation updates. You think documentation is someone else's responsibility.

Nobody's wrong. We just never agreed.

Every ticket becomes a negotiation: "Is this really done, or done enough?"

And that feature I mentioned? The one that took 9 days instead of 3?

I forgot to apply my own error system and spent overtime retrofitting it. We had to refactor how Tailwind works in our monorepo—something we'd never anticipated. Public documentation wasn't in the scope, but integrators needed it. We fixed technical debt along the way because we couldn't ignore it once we saw it.

None of this was hidden complexity. It was all knowable work. We just never made it explicit.

The experiment: make the implicit explicit

So here's what I'm trying: a Definition of Done. A shared agreement about what "complete" actually means.

Not a theoretical document. Not a 50-item checklist. A living agreement that says:

  • Here's what's always included
  • Here's what depends on context
  • Here's what's never assumed

When a developer picks up a ticket, they know the complete scope without asking. When Product writes a ticket, they understand what they're buying. When I review code, I can point to specific missing items without it feeling arbitrary.

Why this might actually work

The DoD doesn't stand alone. It references systems we already use but never documented properly.

Our error system exists—I built it, it's in the code, it works. But it's scattered across READMEs, tribal knowledge, and code examples. The DoD will say "error handling: follows Error System," and that system will be properly documented with why it exists, how it works, and what to check.

Same for internationalization patterns, monorepo structure, naming conventions—systems that exist implicitly but need explicit documentation.

Where does this live? Confluence. Yes, Confluence. I know. Nobody's excited about it. But it's what we have, and perfect is the enemy of done—ironic, given the topic.

What happens Monday

Monday morning, I'm running a workshop with the frontend team.

We're not defining "my" DoD. We're defining ours. Co-created, not imposed. Because if they don't own it, they won't use it.

The agenda:

  1. List everything that should always be done on tickets
  2. Classify each item: always included, sometimes included, or never assumed
  3. Estimate the real impact on ticket time
  4. Decide where to document it
  5. Agree on how to apply it

Then I spend this week consolidating what we decided. Documenting the DoD, migrating our scattered systems to one place, creating the structure we agreed on.

Next week, we test it on real tickets with real measurements.

What happens when estimates meet reality

I expect estimations to roughly double compared to our current "feature only" estimates.

But—and this is critical—the total time from ticket start to actual completion should stay the same or improve. Because we're making visible what we were already doing: the rework, the forgotten requirements, the debt accumulated silently.

Before: estimate 2 days, deliver in 5 days (with hidden rework). Product sees 2, gets frustrated when it takes 5.

After: estimate 5 days, deliver in 5 days. Product sees 5, makes informed decisions.

The second scenario is honest. And honesty creates space for actual optimization.

What could go wrong

Product might refuse the higher estimates. "We can't afford that."

The team might find the DoD bureaucratic. "More overhead."

The documentation might not get used. "Nobody reads Confluence anyway."

I might be solving the wrong problem entirely.

These are real risks. I don't have guarantees.

What I do have: a team that's already asking for this, clear hypotheses to test, and a plan to measure actual impact over two sprints. If it doesn't work, we'll know why. If it does, we'll have data to expand it.

Why I'm doing this anyway

Because the current state isn't sustainable.

Estimations are fiction. Overtime is normalized. Technical debt accumulates silently. New developers take months to understand implicit rules.

Something has to change.

A Definition of Done won't solve everything. But it might create a shared language about what work actually involves.

And when people share a language, fewer things need real-time clarification. Documentation gets referenced instead of people getting interrupted. Decisions get recorded instead of lost.

Not because we engineered an async-first culture. Just because we removed enough friction that clarity became the default.

Why I'm writing this now

So why write about this before I know if it works?

Partly because writing forces me to think clearly. If I can't explain the hypothesis without handwaving, I probably don't understand it.

Partly because public documentation creates accountability. Harder to quietly abandon an experiment when you've told the internet about it.

And partly because I'm tired of reading polished case studies where everything worked perfectly and everyone clapped. The sanitized success story teaches nothing. The messy reality—the resistance, the pivots, the "oh fuck I was completely wrong about that"—that's where the actual learning lives.

In two sprints, I'll know if this DoD experiment holds or crashes. Either way, I'll write about what actually happened. Not the LinkedIn version. The real one.

If you're dealing with similar chaos—estimations that are fiction, teams speaking different languages, the eternal question of "is this really done?"—I'm curious what you've tried.

If you've tried to formalize your DoD or battle implicit scope boundaries, I'd love to hear how it went—especially the failures. Drop a comment or reach out.

The failures are usually more instructive anyway.

This is the beginning of the experiment. Let's see if I'm solving the right problem.


Views and experiments described here are my own and don't represent my employer.


Top comments (0)