Guide · Backlog
The best user story format, with acceptance criteria
A working format for user stories that survives sprint planning, refinement, and the QA conversation — with templates and worked examples.
User stories are tiny pieces of writing that have to do an unreasonable amount of work. They have to capture a real user need, fit in a sprint, carry acceptance criteria precise enough for QA, and stay distinct from the seven other stories sitting nearby in the backlog. Most stories fail one of those tests. This guide is the format that consistently passes all four.
The classic As-a / I-want / So-that statement
The standard story statement remains the most useful:
As a [persona], I want [capability] so that [benefit].
Three rules that keep this from going wrong:
- The persona is a real role from your stakeholder register, not a category. "User" is not a persona. "Returning premium customer" is.
- The capability is user-facing, not system-facing. "I want to filter my order history by date" is good. "I want the API to support a date filter" is a technical task masquerading as a story.
- The benefit is the actual user value, not a restatement of the capability. The test: would deleting the so-that clause change what gets prioritised? If not, rewrite it.
Acceptance criteria: plain English and Gherkin
A story without acceptance criteria is a wish. The format that consistently works is plain-English ACs first, Gherkin scenarios second. Plain English makes the AC reviewable by the product owner; Gherkin lets QA derive test cases.
Plain-English AC: Returning premium customers can filter the order history view by a date range. The filter persists across sessions. Empty results show a clear empty-state message with a link back to the full history.
Scenario: Filter to last 30 days returns matching orders Given I am a premium customer with orders in the last 90 days When I open Order History and apply the "Last 30 days" filter Then I see only orders placed in the last 30 days And the filter remains applied when I return to the page
Two Gherkin scenarios — happy path and one primary edge case — is almost always enough. More than five and the story is too big.
The INVEST checklist (the one that matters)
INVEST is the standard quality test. The version that actually applies in real refinement:
- Independent. Can be developed without coordinating with other stories in the same sprint. If two stories must land together, they are one story.
- Negotiable. The how is up to the team. If the story over-specifies UI or implementation, take it out.
- Valuable. A real user benefit, not a technical task. Internal-only refactors belong as tech-debt tickets, not user stories.
- Estimable. The team can give a confident estimate after refinement. If they can't, the AC is too vague.
- Small. Fits in one sprint with margin. Multi-sprint stories should be epics.
- Testable. QA can write the test cases directly from the AC. If they need to interpret, the AC is incomplete.
Story fields beyond the statement
A backlog-ready story carries metadata, not just text. The minimum set:
- Stable ID (e.g. STORY-204) referenced from tickets and code.
- Epic mapping.
- Persona (from your stakeholder register).
- Story points (rough estimate).
- Priority (MoSCoW or numeric).
- Source: which BR or FR this story derives from.
- Plain-English ACs and Gherkin scenarios.
- Dependencies (if any — and if many, the story is wrong).
Common pitfalls in user-story writing
- The "As a user" everything. If every story starts with "As a user", you have a persona problem. Force the persona to be specific.
- The acceptance-criteria copy-paste. If the same AC appears in 12 stories, it belongs as a definition of done, not in individual ACs.
- The "epic disguised as a story" problem. A story that needs more than 8 ACs is an epic. Split it.
- The hidden tech debt. "As a developer, I want the API to be refactored" is not a user story. It is a tech-debt ticket. Track those separately.
- The orphan story. A story with no source (no BR, no FR, no business decision) should be flagged. It might be a discovered gap, or it might be invented work.
Templates you can copy
Story ID: STORY-NNN Epic: <epic name> Persona: <persona from stakeholder register> Source: <BR-ID or FR-ID> Priority: <Must / Should / Could / Won't> Story points: <rough estimate> As a <persona>, I want <capability> so that <benefit>. Acceptance criteria (plain English): - <criterion 1> - <criterion 2> - <criterion 3> Scenarios (Gherkin): Scenario: <happy path name> Given <precondition> When <action> Then <expected outcome> Scenario: <primary edge case> Given <precondition> When <action> Then <expected outcome>
Generating stories at scale, faithfully
For backlogs above 30–40 stories, the hand-writing approach stops scaling. Generic AI tools produce stories that read fine and break in refinement — invented personas, fabricated ACs, edge cases that have nothing to do with the system. The pattern that works is retrieval-grounded generation against your real discovery files and FRD.
See Reqify's AI User Stories Generator — generates the full set with personas from your register, ACs traced to source, Gherkin scenarios for happy path and primary edge cases, INVEST checks, and one-click push to Jira.
Related: AI BRD Generator · AI FRD Generator · How to write a BRD