How to Write Acceptance Criteria That Developers Actually Understand

ScrumPoi · · 10 min read

How to Write Acceptance Criteria That Developers Actually Understand

“Our Acceptance Criteria Are Fine” (No, They’re Not)

If your team keeps “almost” finishing stories, arguing in refinement, or discovering edge cases during QA, your acceptance criteria are not fine.

You’re not alone:

  • In one Atlassian survey, over 50% of teams said unclear requirements were a top cause of rework.
  • A study by the Project Management Institute found that poor requirements gathering causes 47% of project failures.

Most teams don’t have a velocity problem. They have a clarity problem. And acceptance criteria are where that clarity lives or dies.

Let’s talk about how to write acceptance criteria that developers actually understand, respect, and can implement without guesswork.


What Acceptance Criteria Are Really For

Not a Wish List, a Contract for Behavior

Acceptance criteria are conditions that must be true for the story to be accepted. That’s it.

They are not:

  • A design spec
  • A UX document
  • A brain dump of “nice to haves”
  • A vague reminder of a meeting you once had

They are a behavioral contract between Product, Dev, and QA:

“When we say this story is Done, we all mean the same thing.”

If your acceptance criteria don’t help someone answer “Is this done?” with a clear yes/no, they’re failing.

Who Acceptance Criteria Are For (Hint: Not Just Devs)

Good acceptance criteria help:

  • Developers know what to build and what’s out of scope.
  • Testers know what to verify and how to break it.
  • Product Owners know what they’re accepting and what to reject.
  • Designers know behavioral constraints (e.g., error states, limits).

If any of those groups still need a follow-up meeting to understand the story, your criteria are not specific enough.


The Core Principles of Developer-Friendly Acceptance Criteria

1. Make Them Binary: Pass or Fail, No “Kinda”

Every acceptance criterion should be something you can test like a switch: it’s either met or it isn’t.

Bad:

  • “The page should load fast.”
  • “The user experience should be intuitive.”

Better:

  • “The page loads in under 2 seconds for 95% of requests, measured over a 24-hour period.”
  • “First-time users can complete sign-up in under 3 steps without needing a help link.”

If a developer can ask, “How fast is ‘fast’?” or “What’s ‘intuitive’?” you haven’t finished writing yet.

2. Focus on Observable Behavior, Not Implementation

Developers don’t need your internal monologue. They need inputs, behavior, and outcomes.

Instead of:

  • “Use Redis to cache results.”
  • “Use a dropdown here.”

Try:

  • “Search results are cached for 10 minutes to reduce response time for repeated queries.”
  • “User can select exactly one option from the list of available roles.”

Let the team decide how to build it. Use acceptance criteria to define what must be true from the user or system perspective.

3. Use a Consistent, Boring Format

Boring is good. Boring is readable. Boring is automatable.

A simple pattern that works:

  • Given [context]
  • When [action]
  • Then [outcome]

Example:

  • Given I am a logged-in user
    When I enter a valid email and click “Save”
    Then I see a success message and my email is updated in my profile

You don’t need to write full Gherkin specs for everything, but using this structure forces clarity.


Practical Examples: Bad vs. Good Acceptance Criteria

Login Feature

Bad:

  • “User can log in.”
  • “Show error on invalid credentials.”
  • “Remember me should work properly.”

Problems:

  • What does “log in” mean? Session length? Device limits?
  • What error? Where? How many attempts?
  • What does “remember me” actually remember?

Better:

  1. Given a registered user with a valid email and password
    When they enter correct credentials and click “Log in”
    Then they are redirected to the dashboard

  2. Given a user enters an incorrect password 3 times in a row
    When they attempt a 4th login
    Then their account is locked for 15 minutes and a lockout message is shown

  3. Given a user checks “Remember me” on login
    When they close and reopen the browser within 7 days
    Then they remain logged in and are redirected to the dashboard

Now devs know exactly what to implement. QA knows exactly what to test. No guessing.

File Upload Feature

Bad:

  • “User can upload files.”
  • “Support common file types.”
  • “Show progress.”

Better:

  1. Given a logged-in user
    When they upload a file of type PDF, DOCX, or PNG up to 10MB
    Then the file is accepted and appears in their “Recent uploads” list

  2. Given a user attempts to upload a file larger than 10MB
    When they click “Upload”
    Then the upload is rejected and an error message is shown: “Files must be 10MB or smaller.”

  3. Given a file upload is in progress
    When the upload has not completed
    Then a progress bar shows the estimated percentage completed

Notice: each one can be tested, automated, and argued about before coding, not after.


Common Mistakes That Make Developers Hate Acceptance Criteria

Mistake 1: Writing Criteria After Development Starts

If your acceptance criteria are written during QA or “as we go,” you’re not writing criteria. You’re writing post-mortems.

Symptoms:

  • Stories “grow” during the sprint.
  • Devs feel blindsided by “Oh, we also need…”
  • QA finds “bugs” that are actually missing requirements.

Fix:

  • Acceptance criteria must exist before the team commits to the story.
  • If you discover new criteria mid-sprint, either:
    • Add a new story, or
    • Re-negotiate the scope of the current one and update the sprint plan.

Stop pretending “just one more acceptance criterion” is free.

Mistake 2: Mixing UX Design Into Acceptance Criteria

“Button should be blue.”
“Use rounded corners.”
“Modal should slide in from the right.”

This belongs in design specs, not acceptance criteria. Devs now have to chase Figma and Jira and reconcile differences.

Fix:

  • Keep acceptance criteria about behavior and rules.
  • Keep visual and interaction details in design tools, linked from the story.
  • If a visual requirement is critical (e.g., accessibility contrast), express it as a measurable rule:
    • “Text in buttons must meet WCAG AA contrast ratio of 4.5:1 or higher.”

Mistake 3: Cramming 20 Criteria into One Bloated Story

If your story has 15–20 acceptance criteria, it’s not a story. It’s a project.

Consequences:

  • Devs cherry-pick the easy parts.
  • QA can’t realistically test everything in time.
  • The story spans multiple sprints “because it’s big.”

Fix:

  • Aim for 3–7 acceptance criteria per story as a rule of thumb.
  • If you go beyond that, ask:
    • “Can this be split into separate behaviors?”
    • “Would a user notice if we shipped this part separately?”

Smaller stories = clearer acceptance criteria = fewer surprises.

Mistake 4: Using Vague Words That Sound Smart but Mean Nothing

Phrases that should trigger an immediate rewrite:

  • “Should be able to…”
  • “Ideally…”
  • “If possible…”
  • “As needed…”
  • “Robust / scalable / user-friendly / performant”

These are wishlist words, not conditions.

Fix:

  • Replace them with numbers, constraints, or examples:
    • “Handle up to 10,000 requests per minute without errors.”
    • “User completes checkout in 3 steps or fewer.”
    • “System recovers from a restart without data loss.”

If you can’t specify it, don’t pretend it’s a requirement.


How to Actually Write Good Acceptance Criteria as a Team

Step 1: Start with the Outcome, Not the UI

Before you touch Jira, answer:

  • What problem is this solving?
  • How will we know it’s working?
  • What behavior will a user or system exhibit when this is done?

Example:

  • Problem: Users abandon the checkout when forced to create an account.
  • Outcome: Users can complete a purchase without registration.

Now write acceptance criteria around that outcome, not around “Add a guest checkout checkbox.”

Step 2: Use Three Lenses: Happy Path, Sad Path, Edge Path

Most acceptance criteria only cover the happy path. That’s where bugs hide.

For each story, deliberately write:

  • Happy path: When everything goes right.
  • Sad path: When the user or system does something wrong.
  • Edge path: When something unusual but realistic happens.

Example for a payment form:

  • Happy: Valid card, sufficient funds → success.
  • Sad: Invalid card number → clear error.
  • Edge: Payment provider times out → retry or show a specific failure state.

Write at least one criterion for each path.

Step 3: Write Criteria Collaboratively in Refinement

If your PO writes acceptance criteria alone and throws them over the wall, expect misunderstandings.

In refinement:

  1. PO presents the user goal and context.
  2. Team asks, “What could go wrong?” and “What about X case?”
  3. Together, you draft acceptance criteria in the ticket.
  4. Devs and QA push back on anything vague or untestable.

This takes 5–10 minutes per story and saves hours of rework.

Step 4: Tie Acceptance Criteria to Test Cases (and Automation)

Your best acceptance criteria can become automated tests.

  • QA can map each criterion to:
    • One or more manual test cases, and/or
    • One or more automated tests (unit, integration, E2E).
  • Devs can write tests using the same Given/When/Then language.

Example:

  • Criterion: “Given a locked account, when the user logs in, then they see a lockout message and cannot access the dashboard.”
  • Automation: E2E test that verifies exactly that flow.

When criteria and tests mirror each other, “Done” stops being a debate.


Concrete Templates You Can Steal

Basic User Story Template

  • Story: As a [type of user], I want [capability], so that [benefit].

  • Acceptance Criteria:

    1. Given [context]
      When [action]
      Then [outcome]

    2. Given [different context]
      When [action]
      Then [outcome]

System Behavior Template

  • Scenario: [System event or scheduled task]

  • Acceptance Criteria:

    1. Given [system state]
      When [event occurs or time passes]
      Then [system performs X within Y time]

    2. Given [failure condition]
      When [event occurs]
      Then [fallback or alert happens]

You don’t need fancy tooling for this. You need discipline.


Tools and Workflows That Make This Easier

  • Add a required “Acceptance Criteria” field in your issue tracker so stories can’t be moved to “Ready” without it.
  • Use checklists in your story template:
    • Happy path covered
    • At least one error/sad path
    • Edge case considered (limits, timeouts, invalid input)
    • Non-functional requirement (if relevant: performance, security, accessibility)

During planning or estimation sessions, tools like ScrumPoi can help your team surface unclear acceptance criteria quickly—if everyone is voting wildly differently on effort, it’s usually a sign your criteria are fuzzy and need work.


What “Good” Looks Like in Practice

You’ll know your acceptance criteria are working when:

  • Devs stop asking, “What exactly do you mean by…?”
  • QA isn’t discovering “requirements bugs” at the end of the sprint.
  • Stories rarely spill over because of “hidden” work.
  • Sprint reviews are boring in the best way: “Here’s what we built. It matches what we agreed.”

This isn’t about writing more documentation. It’s about writing just enough, just clearly enough, at the right time.


Wrap-Up: Clarity Is a Feature

If your team keeps tripping over stories that are “done but not really done,” don’t blame velocity, don’t blame estimates, and don’t blame the developers.

Fix your acceptance criteria.

  • Make them binary and testable.
  • Describe behavior, not implementation.
  • Cover happy, sad, and edge paths.
  • Write them together, before you commit.

Developers don’t need more words. They need better words.

Start with the next story in your backlog. Rewrite its acceptance criteria using the patterns above. Then watch how much smoother the sprint goes.

Keep reading

More on the topics this article touches.