Sertaç Yıldırım field notes

Home → Part 14

Definition of Done: A Quality Contract, Not a Checklist

Wednesday 26 November, 09:30. A message from the call centre: “Since yesterday, customers are getting the error ‘This IBAN does not belong to you’. The IBANs are theirs.” The story behind the error had moved to the Done column six days earlier. All six items of our DoD were ticked.

Summary
  • Our “done” ended in the test environment. For 26 hours, the story wrongly rejected 212 of 1,460 withdrawal requests (14.5%). There was no alert; the call centre noticed.
  • A DoD is a contract, not a checklist. A checklist is for the memory of the person doing the work. A contract is for the people who rely on that work: the PO, the call centre and the customer.
  • There are three layers: story, sprint and production. Each layer means a different “done”. We only had the first one.
  • The team changes the DoD, in the retro, for the next sprint. The PO cannot relax it to meet a date. Every new item has a cost in capacity.
  • When it breaks, keep the work open. Not a new bug ticket: you reopen the same story and remove it from the done count.

From the field: a story with six ticked boxes

The story was: “In a withdrawal request, reject the request if the name of the IBAN owner does not match the name of the account owner.” A customer can only withdraw money to an account in their own name; this is a regulatory rule. The bank’s name check service did the matching.

It was in Sprint 12, from 10 to 21 November. It moved to Done on Thursday 20 November. On that day, our DoD had six items:

DoD v1 — November 2025
1. Code reviewed (at least one approval)
2. Unit and integration tests green in CI
3. Code coverage above 80%
4. Deployed to the test environment
5. Acceptance criteria checked in the test environment
6. Approved by PO

All six were true. Code coverage was 91%. We had tried twelve scenarios in the test environment against the bank’s sandbox service. We showed it in the review on 21 November, and the PO approved it. It went live with the weekly release on Tuesday 25 November at 10:00.

The sandbox returned the name exactly as we sent it. The production service returned only the first given name and the surname. “Fatma Nur Kaya” was three words in our records and “FATMA KAYA” in the bank’s answer. Our comparison ignored upper and lower case, but it expected the full name to match. Every customer with two given names was rejected. All twelve test scenarios used customers with one given name.

It lasted 26 hours. From Tuesday 10:00 to Wednesday 12:00, 212 of 1,460 withdrawal requests were wrongly rejected, which is 14.5%. There was no metric for the rejection rate, so there was no alert either. There was also no switch to turn the check off. To disable it, we had to ship a rollback release, and that took until 12:00. The real fix took a day and a half in Sprint 13.

I had written the DoD. In the Daily Standup post, I even gave its summary: the tests passed, CI/CD deployed to the relevant environment, and the feature was checked there. I chose the words “relevant environment”, and in my head it meant the test environment. Our definition said a story was done. It did not say it was done where the customer sees it.

Done ends where the customer sees it.

What a DoD is for: a contract

The Scrum Guide defines the DoD as the commitment of the increment. The moment an item meets the DoD, an increment is born. An item that does not meet it cannot be released. It cannot even be shown in the sprint review; it goes back to the product backlog. This is a much stronger sentence than a checklist.

This is how I put the difference. A checklist is for the memory of the person doing the work, so they do not forget something. A contract is written for the people who rely on the work. The moment we say “done”, other people start to rely on things:

  • The PO plans the next sprint assuming the work runs.
  • The call centre answers customers based on that work.
  • Other teams build their own work on top of it.
  • The velocity chart counts it as done, and future estimates depend on it.

On 26 November, all four had relied on something wrong. The call centre did not even know about the new rejection message, so they did not know what to tell customers. The list was not wrong. It just did not say what anyone was relying on.

A checklist is for the person doing the work. A contract is for the people who rely on it.

What it should look like: three layers

In the Sprint 13 retro on 5 December, we split the DoD into three layers. Each layer means a different “done”, and we check it at a different time:

LayerWhat it saysItemsWhen
StoryThis item works on its ownReview, tests in CI, at least one example with production-like data, logs and a metric addedBefore the card moves to Done
SprintThe items work together, and the people affected knowRegression tests green, release notes written, call centre informed about changes customers can seeBefore the review
ProductionIt works where the customer sees itChecked in production, dashboard and alert in place, switch-off path tested, 24 hours of monitoring24 hours after the release

We also added a column to the board: “Live, being watched”. A card only reaches Done through that column. With this setup, the IBAN story would never have reached Done. On the first day, the rejection rate alert would have fired.

DoD v2 — December 2025 (in the repo: docs/bitti-tanimi.md)
STORY
  - Code reviewed (at least one approval)
  - Unit and integration tests green in CI
  - At least one example with production-like data
    (customer with two given names, Turkish letters,
     upper case, spaces)
  - Log line and metric for the new behaviour

SPRINT
  - Regression tests green
  - Release notes written
  - If customers can see the change, call centre
    informed (what changed, what to tell customers)

PRODUCTION
  - Checked in production with at least one real transaction
  - Visible on the dashboard, alert fires above a threshold
  - Switch-off path exists and was tested (flag or rollback)
  - Watched for 24 hours, then "done"

Removed: "code coverage above 80%" (the IBAN story had 91%)

Who checks each layer?

Writing the layers was easy. Deciding who checks each one took a week. In the end, we set it up like this:

  • Story layer: the person who did the work and the person who reviewed the code. The reviewer asks about the code, and also about the example with production-like data.
  • Sprint layer: one developer, a different one each sprint, one day before the review. This person writes the release notes and the two-line note for the call centre.
  • Production layer: the person who shipped the release. After 24 hours, they look at the dashboard. If the rejection rate or error rate is below the threshold, they move the card to Done themselves.

We added one more rule. The person who moves the card to Done writes the layer’s result on the card in one line: “Tried with 3 real requests in production, rejection rate 0.8%, alert threshold 3%.” A sentence, not a ticked box. Six months later, anyone who opens that card can read what people relied on.

A feature flag is a setting that turns a feature on or off without a new release. I will not go into testing separately here. In the Epic, Story, Task post, I suggested putting tests inside the DoD instead of on a separate card. That rule still stands. The question here is not where testing sits. It is where “done” ends.

Why did we remove the coverage item? Because it told us nothing. A story with 91% coverage rejected one in seven withdrawal requests. The item gave a feeling of safety, not something you could rely on. Only items that someone really relies on go into the contract.

Who changes the DoD

The Guide is clear. If the organisation has a standard, the team follows it as a minimum. If not, the Scrum team creates the DoD. We have no organisation standard, so we set our own rules:

  • A change is proposed in the retro. The action rule from the Retrospective post applies here too: definition, owner, deadline.
  • The team decides, and the PO listens. The PO can ask for an item to be added. The PO cannot relax an item to meet a date.
  • It does not change in the middle of a sprint. It applies from the next sprint. A DoD that changes mid-sprint also quietly changes that sprint’s commitment.
  • Every addition has a cost, and we write the cost down. The new items added about half a person-day per story. In Sprint 14, we planned seven items instead of nine.

The last point got the most push-back. “So we will do less work?” No, we will count less work as done. The difference was an item that said “done” in Sprint 12 but needed a day and a half more work in production.

When it breaks: keeping the work open

On 26 November, our first reflex was to open a new bug ticket. If we had done that, the story would have stayed “done”. The Sprint 12 count would have stayed at seven. The bug would have taken capacity from Sprint 13 as “other work”. On paper, nothing would have been broken.

Instead, we set this rule:

  1. Within 7 days of going live, if a bug breaks the acceptance criteria, we reopen the same story. After 7 days, it is a normal bug ticket.
  2. The reopened story is removed from the done count of its sprint. The table in the Definition of Ready post says “7 / 8” for Sprint 12. Under today’s rule, that number is 6 / 8. I am not editing that post; this post is the correction.
  3. Relaxing the DoD is recorded. If work has to go live without meeting one DoD item, it can. But it does not count as done. Three things go on the card: which item is missing, who made the decision, and when the missing part will be finished. The card stays open until then.

The rule had a side effect I did not expect. In the days after a release, the team started to look at the dashboard on their own, because work that came back from production now came off their own sprint count. Nobody asked them to. The number did.

Relaxing the DoD does not make the work faster. It makes counting unfinished work as finished faster.

How it breaks

Do
  • Split the DoD into story, sprint and production layers
  • Add a “live, being watched” column before Done
  • Ask for at least one example with production-like data
  • Reopen the same story when work comes back from production
  • Write down the capacity cost of every new item
Don't
  • Use vague words like “relevant environment”
  • Keep items nobody relies on (a coverage percentage)
  • Quietly relax the DoD to meet a date
  • Hide a production bug behind a new bug ticket
  • Change the DoD in the middle of a sprint

What to watch

Sprints 9–12
DoD v1
Sprint 14
DoD v2
Planned items (per sprint)8–97
Items done29 (in four sprints)6
Came back from production within 7 days4 / 29 (14%)0 / 6
Who noticed the production bug firstIn all 4 cases, a customer or the call centre

Sprint 14 is one sprint. Zero is not a result; it is a start. The production layer also has an uncomfortable cost. We ship a weekly release, so work that misses the Tuesday 16 December release cannot be “done” inside the sprint. The seventh item was finished as code, went live on 23 December, and will count in Sprint 15. We accepted this on purpose.

The row I really watch is the last one: who sees the next bug first. If the alert sees it, the production layer of the DoD is working. If a customer sees it, it is not.

Checklist

Before you move the card to Done
  • Does our DoD clearly say in which environment “done” ends?
  • Did we try at least one example with production-like data?
  • If this breaks in production, who will see it first: an alert or a customer?
  • Is there a way to switch it off, and did someone actually test it?
  • If customers can see the change, does the call centre know what to say?
  • Is there an item in our DoD that nobody relies on?
  • Did we remove the stories that came back from production from the last sprint’s done count?

Conclusion

The message from the call centre on the morning of 26 November was not a test failure. It was a broken contract. Six boxes were ticked, and all six were true. But none of them said what the people relying on the work were relying on.

Now a card waits 24 hours before it moves to Done. This is not slowness. It is the price of never again learning the meaning of “done” from the call centre.

Sources

The DoD as the commitment of the increment, the rule that an item that does not meet it cannot be shown in the review, and the link between an organisation standard and the team’s DoD come from the Scrum Guide (2020). The three layers, the 7-day rule and keeping the work open are rules we set in our own team after this incident.