Posts

How to write acceptance criteria that actually prevent rework

Agile team collaborating around a table with sticky notes and a laptop, discussing requirements for a user story during a backlog refinement sessionAgile team collaborating around a table with sticky notes and a laptop, discussing requirements for a user story during a backlog refinement session
Kelly Lewandowski

Kelly Lewandowski

Last updated 19/02/20268 min read

Requirements-related issues cause nearly half of all software defects. Most of those trace back to the same root problem: the team built what they thought was asked for, not what was actually needed. Acceptance criteria are the fix. They turn a vague user story into a testable contract between the product owner and the development team. When written well, they kill the "but I thought it should..." conversations that derail sprint reviews. This guide covers the two main formats, real examples you can adapt, and the mistakes that trip up experienced teams.

What acceptance criteria are (and aren't)

Acceptance criteria are the conditions a user story must satisfy before it's considered complete. They answer one question: "How will we know this works?" They're not the same as a definition of done. The DoD is a universal quality standard that applies to all work (code reviewed, tests written, deployed to staging). Acceptance criteria are specific to a single story.
Acceptance criteriaDefinition of Done
ScopeOne user storyAll work items
FocusWhat the feature does for usersHow well it's built
Who writes itProduct Owner + teamThe whole Scrum Team
Example"User can filter by date range""Code reviewed by at least 1 dev"
Both must be satisfied before a story is done. If you're still building out your DoD, our Definition of Done Generator can help you get started.

The two main formats

Checklist format (rule-based)

A simple list of pass/fail conditions. Best for straightforward features where the expected behavior is clear.
Password reset feature:
- "Forgot password" link appears on the login page
- Clicking it prompts for an email address
- Valid email receives a reset link within 60 seconds
- Reset link expires after 24 hours
- New password must meet existing password requirements
- After reset, user is redirected to login with a success message
- Invalid email shows: "If this email exists, a reset link has been sent"
When to use it: Simple features, UI requirements, business rules, validation logic. Most of your stories will use this format.

Given/When/Then format (Gherkin)

A structured scenario format from Behavior-Driven Development. Each scenario describes a precondition, an action, and an expected result.
Scenario: Applying a valid discount code
Given the user has items in their cart totaling $100
And a valid 20% discount code "SAVE20" exists
When the user enters "SAVE20" in the discount field
And clicks "Apply"
Then the cart total updates to $80
And a message "Discount applied" appears

Scenario: Applying an expired discount code
Given the discount code "OLD10" expired yesterday
When the user enters "OLD10" and clicks "Apply"
Then the cart total remains unchanged
And an error message "This code has expired" appears
When to use it: Complex workflows with multiple paths, or features you plan to automate with BDD tools like Cucumber or SpecFlow. Two side-by-side documents showing the checklist format and Given/When/Then format for acceptance criteria, with colorful annotations highlighting the differencesTwo side-by-side documents showing the checklist format and Given/When/Then format for acceptance criteria, with colorful annotations highlighting the differences

Which format should you pick?

Most teams land on a hybrid approach: checklist for simple stories, Given/When/Then for anything with complex branching or multiple user paths. Don't overthink it. Pick whichever format communicates the requirements more clearly for that specific story.

Five rules for writing good acceptance criteria

1. Define the what, not the how

Bad: "Use a modal component with a 400ms fade-in animation" Good: "Confirmation dialog appears before the item is deleted" Criteria describe outcomes. Implementation is the developer's job.

2. Make every criterion testable

If you can't answer "yes" or "no" to whether a criterion is met, it's too vague. Bad: "The page should load quickly" Good: "Search results load within 2 seconds for up to 500 results"

3. Cover the sad path

For every happy path, write at least one error scenario. What happens with invalid input? A dropped connection? Missing permissions?

4. Keep criteria independent

Each criterion should be verifiable on its own. If criterion #4 only makes sense after reading criteria #1 through #3, you've written a spec, not acceptance criteria.

5. Write them before sprint planning

Acceptance criteria written during development are descriptions, not requirements. Write them during backlog refinement so the team can estimate accurately during planning poker.

Real-world examples

E-commerce search filter

User story: "As a shopper, I want to filter products by multiple categories so I can narrow results to what I'm looking for."
  • Filters display all available product categories
  • Users can select multiple categories at once
  • Results update in real-time without page refresh
  • Applied filters show as removable badges
  • "Clear all" button removes all active filters
  • Result count updates to reflect active filters (e.g., "Showing 47 results")
  • No matching results shows: "No products match your filters. Try broadening your selection."
  • Filter state persists when navigating back from a product detail page

Team invitation flow

User story: "As a team lead, I want to invite members by email so we can start collaborating."
Scenario: Successful invitation
Given I am on the team settings page
When I enter "alex@company.com" in the invite field
And click "Send Invite"
Then an invitation email is sent within 60 seconds
And the email appears in my "Pending Invitations" list
And a success message confirms the invitation was sent

Scenario: Duplicate invitation
Given I already invited "alex@company.com"
When I enter the same email and click "Send Invite"
Then a warning appears: "Invitation already sent to this email"
And I can choose to resend or cancel

Scenario: Invalid email format
Given I am on the team settings page
When I enter "not-an-email" and click "Send Invite"
Then an inline error appears: "Enter a valid email address"
And no invitation is sent

Notification preferences

User story: "As a user, I want to control which notifications I receive so I'm not overwhelmed by alerts."
  • Settings page shows toggle for each notification category
  • Changes save automatically (no separate "Save" button)
  • Toggling a category off stops all notifications of that type within 5 minutes
  • At least one notification channel must remain active (prevent accidental opt-out of everything)
  • "Reset to defaults" restores the original notification settings
  • Changes apply across all devices
A developer reviewing a user story card with clearly written acceptance criteria, checking items off one by oneA developer reviewing a user story card with clearly written acceptance criteria, checking items off one by one

Common mistakes

Being too vague. "The system should be user-friendly" isn't testable. Replace subjective language with measurable conditions. Prescribing implementation. "Use Redux for state management" belongs in a tech spike, not in acceptance criteria. Describe what the user experiences, not how the code works. Only writing the happy path. If your criteria only cover the sunshine scenario, your team will discover edge cases mid-sprint and either cut corners or blow the estimate. Writing criteria too late. Criteria written during development are retroactive justifications, not requirements. Define them during refinement, refine them during sprint planning. Making criteria too granular. If your criteria read like a test script with 30 steps, you've gone too far. Aim for 5-10 criteria per story. If you need more, the story is probably too big and should be split into smaller stories.

A quick self-check

Before committing a story to a sprint, run through this:

Every criterion has a clear pass/fail outcome

At least one error or edge case scenario is covered

No implementation details are prescribed

A developer and tester reviewed the criteria together

The story is small enough to finish in one sprint

If any of those fail, the story needs another round of backlog refinement before it's sprint-ready.

Writing acceptance criteria faster

The "Three Amigos" approach works: get the product owner, a developer, and a tester in the same room for each story. The PO explains intent, the developer spots technical edge cases, and the tester pokes holes with "what if...?" questions. If you're writing user stories and need a starting point, our Acceptance Criteria Generator can draft initial criteria from a story description. It gets you the first 80% quickly so your team can spend refinement time on the tricky edge cases instead of staring at a blank page.

Aim for 5-10. Fewer than 3 usually means you're missing scenarios. More than 12 suggests the story should be split into smaller pieces.

The product owner owns them, but they should be refined collaboratively with the development team and QA during backlog refinement. The "Three Amigos" approach (PO + dev + tester) catches gaps early.

Acceptance criteria define what the feature should do at a high level. Test cases are the detailed steps QA uses to verify those criteria. One acceptance criterion might map to several test cases.

Yes, when they're specific to the story. "Search results load within 2 seconds" belongs in AC. "All code must have 80% test coverage" belongs in your Definition of Done since it applies to all work.