Core DeliveryFoundational7 min read

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.

LetterMeansWhy it matters
I -- IndependentCan be built and delivered without waiting on other storiesPrevents blocked work and tangled dependencies
N -- NegotiableThe "how" is flexible; only the outcome is fixedGives engineering room to find the best solution
V -- ValuableDelivers something a user or stakeholder cares aboutPrevents building things nobody asked for
E -- EstimableThe team can roughly gauge the effortIf you can't estimate it, you don't understand it yet
S -- SmallCan be completed in one iteration or lessLarge stories hide complexity and create carry-over
T -- TestableYou can verify it works without ambiguityAcceptance 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 schemaStory 1: User can request a password reset and receive an email (happy path only)
Story 2: Build password reset API endpointStory 2: User sees an error if email doesn't exist in the system
Story 3: Build password reset UIStory 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.

Want help with story writing?

I coach teams on this practice. Let's talk about your situation.

Get in touch