Story Writing
Writing stories that developers can actually build from
A user story is a contract between product and engineering. Not a legal contract -- a shared agreement about what "done" means before anyone writes a line of code.
Most story-writing problems aren't about format. They're about clarity. When developers keep asking "what do you actually want?" or stories grow mid-sprint, the story wasn't ready for development. The structure below fixes that.
The INVEST standard
Good stories are INVEST-compliant. This isn't a checklist to memorize -- it's a diagnostic. When a story feels off, check which letter is missing.
| Letter | Means | Why it matters |
|---|---|---|
| I -- Independent | Can be built and delivered without waiting on other stories | Prevents blocked work and tangled dependencies |
| N -- Negotiable | The "how" is flexible; only the outcome is fixed | Gives engineering room to find the best solution |
| V -- Valuable | Delivers something a user or stakeholder cares about | Prevents building things nobody asked for |
| E -- Estimable | The team can roughly gauge the effort | If you can't estimate it, you don't understand it yet |
| S -- Small | Can be completed in one iteration or less | Large stories hide complexity and create carry-over |
| T -- Testable | You can verify it works without ambiguity | Acceptance criteria make this concrete |
Anatomy of a story
Title
A short, verb-forward phrase that describes what happens. "User can reset password via email" not "Password reset feature."
User story sentence (optional)
As a [role], I want [action] so that [outcome].
This format is useful when you need to explain why something matters. It's not required for every story -- sometimes the title and acceptance criteria are enough.
Acceptance criteria
This is the part that matters most. Acceptance criteria define the boundary of "done" in concrete, testable terms.
Write them in Given/When/Then format (Gherkin) -- the same format used in test-driven development to generate automated tests:
Given I am a logged-in user on the settings page
When I click "Reset Password"
Then I receive a password reset email within 60 seconds
And the email contains a link that expires after 24 hours
Rules for good acceptance criteria:
- Observable behavior, not implementation. "User sees a success message" not "System calls the email API."
- Specific thresholds. "Within 60 seconds" not "quickly." "Expires after 24 hours" not "expires eventually."
- Edge cases included. What happens if the user clicks the link twice? What if their email doesn't exist?
- Nothing hidden. If there's a business rule ("max 3 reset attempts per hour"), put it in the criteria. Don't assume the developer will know.
Vertical slicing
The most common story-writing mistake is horizontal slicing -- building layer by layer (database first, then API, then UI). This means nothing is demoable until everything is done.
Vertical slicing means each story delivers a thin, working slice through the entire stack. The first story might only handle the simplest case, but it works end-to-end.
| Horizontal (avoid) | Vertical (prefer) |
|---|---|
| Story 1: Build password reset database schema | Story 1: User can request a password reset and receive an email (happy path only) |
| Story 2: Build password reset API endpoint | Story 2: User sees an error if email doesn't exist in the system |
| Story 3: Build password reset UI | Story 3: Reset link expires after 24 hours; user sees a clear message |
Vertical slices are demoable, testable, and shippable independently. They also expose integration issues early instead of at the end.
Common problems and fixes
"The story keeps growing mid-sprint." The acceptance criteria were too vague. Before the story enters iteration planning, ask: "Could two developers independently read this and build the same thing?" If not, tighten the criteria.
"Developers are interpreting the story differently than I intended." Walk through the acceptance criteria together before work starts. Fifteen minutes of alignment saves days of rework.
"The story is too big to fit in one sprint." Slice it vertically. Find the simplest version that delivers value end-to-end. Ship that first, then layer on complexity.
"I don't know enough to write good criteria." That's a sign you need a spike or discovery story first. Write a time-boxed research story: "Spend 4 hours investigating X so we can write concrete acceptance criteria for the implementation story."
Try this today
Pick one story from the top of your backlog. Read the acceptance criteria out loud. Ask yourself: could a developer who knows nothing about this project build exactly what I want from these criteria alone? If not, rewrite the criteria until the answer is yes.
Related practices
Related services
Want help with story writing?
I coach teams on this practice. Let's talk about your situation.
Get in touch