A Definition of Done (DoD) is supposed to reduce ambiguity. In practice, many teams end up with either a vague sentence that nobody checks, or a long compliance list that makes shipping feel like punishment.
Small teams feel this tension the most. You have limited time, you context switch constantly, and you cannot afford repeated defects and follow-up work. A usable DoD helps you ship confidently while keeping the process lightweight.
This post shows a simple approach: treat “done” as a layered set of outcomes, not a single giant checklist. Then make it visible, measurable, and easy to apply to real work.
What a Definition of Done should solve
A DoD is a shared contract for what “finished” means at the end of a task, story, or change. It protects your team from two common failure modes: shipping too early and paying for it later, or polishing forever because nobody agrees what “good enough” is.
For small teams, a good DoD specifically aims to:
- Prevent rework loops by capturing the minimum quality bar before you merge or release.
- Make handoffs safe even when one person is “the only one who knows that part.”
- Keep velocity honest by avoiding “done” work that still needs documentation, testing, or operational setup.
- Enable predictable releases by forcing critical checks (like monitoring or rollback plans) to happen before production.
Importantly, your DoD is not a performance metric or a way to punish mistakes. It is a tool for clarity. If it becomes a weapon, people will route around it.
Principles for a practical DoD
Before you write any bullet points, align on a few principles. These keep your DoD from turning into either mush or bureaucracy.
- Outcomes over rituals. Write what must be true, not which tool button someone must click.
- Default to “yes.” If a DoD item is often “not applicable,” make that explicit instead of forcing work that adds no value.
- Small enough to remember. Your default DoD should fit in one screen. Add extensions for special cases.
- Separate merge-ready from release-ready. Many teams need two bars: one for integrating safely, another for going live.
- Make it auditable. Each item should have an obvious place to verify (PR description, ticket, monitoring dashboard, release notes).
If you already use a ticketing system, treat the DoD as a set of required fields or checkboxes for certain types of work. If you do not, a simple shared template is enough.
Build a layered DoD
A layered DoD is the easiest way to stay strict on what matters without being strict about everything. Think of it as a base layer that applies to most work, plus add-on layers for higher-risk changes.
Layer 1: Merge-ready basics
This layer prevents the most common “it works on my machine” outcomes. It should apply to nearly every change.
- Acceptance criteria are met and verified by the author.
- Risky logic has at least one targeted test (unit, integration, or a documented manual check).
- Code is readable enough that a future you can change it safely (names, structure, comments where needed).
- PR describes what changed and why, including any tradeoffs.
Layer 2: Release-ready quality and safety
This layer applies when a change can affect users or data. It focuses on shipping safely, not just merging cleanly.
- A rollback approach exists and is realistic (revert, feature flag off, config toggle).
- Observability is in place for the change (logs, metrics, or an alertable symptom).
- User-facing changes have basic copy review and error-state handling.
- Any data change includes a plan for backfill, verification, and reversal if needed.
Layer 3: High-risk extensions (only sometimes)
Use extensions for categories where failure is expensive: authentication, billing, permissions, deletes, migrations, and performance-critical paths.
For example, billing changes may require an extra set of checks: test in a sandbox, verify idempotency, confirm ledger entries, and document support steps.
Here is a compact way to represent layers in a template. Keep it conceptual and editable, not “hard coded” into your process:
Definition of Done (DoD)
- Layer 1 (Merge-ready): always
- Layer 2 (Release-ready): when user/data impact
- Layer 3 (Extensions): when category matches (billing/auth/migrations/etc.)
Each item must be verifiable in: PR + ticket + release note (if shipped)
Example: a small team shipping a risky change
Imagine a two-person SaaS team adding “annual billing” to an existing subscription system. The feature touches price calculations, invoices, webhooks, and support workflows. This is exactly the kind of work where “done” gets fuzzy.
Using a layered DoD, they might apply it like this:
- Layer 1: The ticket’s acceptance criteria include creating an annual plan, switching an existing customer, and seeing correct totals. The author adds a targeted test around prorations and writes a PR summary that explains the new billing rules.
- Layer 2: They add a metric for invoice creation failures and a log event that includes customer ID and plan type. Rollback is “turn off annual plan flag” and keep monthly plans unchanged.
- Layer 3 (billing extension): They perform a documented manual verification in a sandbox environment, confirm webhook retries do not duplicate invoices, and write a short internal note: “How support can identify annual plan customers and what to do if an invoice fails.”
The result is not perfection. It is a clear minimum bar that prevents the predictable failures: duplicated charges, silent invoice failures, and support confusion.
Copyable Definition of Done checklist
You can copy this and adjust it to your context. If you already have a working process, keep what is working and only add what you routinely regret skipping.
- Scope: The ticket clearly states what is included and what is excluded.
- Verification: There is a test or a documented manual check that proves the change works.
- Reviewability: PR description explains intent, not just implementation details.
- Failure modes: Known edge cases are handled, or explicitly deferred with a note.
- Safety: A rollback path exists and is stated (revert, flag, config).
- Visibility: There is a way to observe success or failure after release (log, metric, alert).
- Docs: Any operational or support impact is documented in a short, searchable place.
- Ownership: Someone is accountable for release and post-release verification.
Key Takeaways
- Make “done” layered: merge-ready, release-ready, and high-risk extensions.
- Write DoD items as verifiable outcomes, not tool-specific rituals.
- Keep the default short, then add strictness only where failure costs more.
- Pair every requirement with a place to confirm it (PR, ticket, release notes, monitoring).
Common mistakes
Most DoDs fail for predictable reasons. These are the ones that show up in small teams again and again.
- Making it a wishlist. If the list includes “refactor nearby code” or “improve architecture” on every change, people will ignore the whole thing. Keep the default bar tight.
- Confusing effort with outcomes. “Two reviewers approved” is not an outcome. “A second person confirmed the acceptance criteria and failure modes” is closer.
- All-or-nothing enforcement. If everything is mandatory for every tiny change, people will either slow to a crawl or start rubber-stamping.
- No explicit exceptions. Emergency fixes happen. Your DoD should have a safe exception path, such as “ship now, then follow up with missing items within 24 hours.”
- Never revisiting it. If your DoD is unchanged for a year, it is probably out of sync with your actual risk profile.
A helpful habit is to add DoD items only after a real incident or a repeated pain. That keeps the list grounded in reality.
When not to use a strict Definition of Done
A DoD is most valuable when you ship changes frequently and the cost of defects is meaningful. There are situations where a strict DoD creates more friction than value.
- Exploration spikes. If the goal is learning, use a “Definition of Learned” instead: what you discovered, what you tried, and what you recommend next.
- One-off internal scripts. If it is truly disposable and low impact, treat it differently. Still document who will run it and how to undo its effects.
- Early prototypes. For prototypes, prioritize speed and clarity of intent. Keep only a few safety checks so you do not accidentally turn a prototype into production without noticing.
The best compromise is to define different DoDs by work type. One size rarely fits all.
FAQ
How detailed should our DoD be?
Detailed enough that two different people would make the same “done or not done” decision. If you need long explanations, make the top-level item short and link to a small internal note describing how to verify it.
Do we need different DoDs for bugs vs features?
Often, yes. Bugs usually need stronger verification (repro steps, test to prevent regressions) while features often need stronger release readiness (docs, support notes). Start with one base DoD and add extensions by category.
Who owns the Definition of Done?
The team owns it collectively, but one person should maintain the text and incorporate changes. Treat it like a living document: propose edits, review briefly, then adopt.
How do we enforce it without being punitive?
Make the DoD easy to satisfy, visible at the point of work (ticket or PR template), and tied to real outcomes. Use retrospectives to adjust it. If people routinely miss an item, either simplify the workflow or rewrite the item to be more achievable.
Conclusion
A useful Definition of Done is not a wall of rules. It is a small, shared agreement that turns “I think it’s finished” into “we can safely ship this.”
Start with a short base layer, add release safety where it matters, and reserve strict extensions for categories that regularly bite you. If your DoD reduces rework and improves confidence without feeling heavy, you have the right one.