This guide will help you write clear and effective user stories for software development.
Writing user stories is a delicate balancing act. A few years ago, I wrote a blog post titled How to be a Great Product Owner, which discussed several high-level concepts around being a Product Owner.
In this post, I’ll go over the key elements of story writing: What a story is, how it relates to a ‘ticket’, what writing in story form means, and the nuanced ways to think about this process.
Story form means we write a narrative — or “story”— to communicate with the engineers who will be implementing a feature.
Writing a story involves this template:
(Line #1) As a ______
(Line #2) So that I can ______
(optional) [When _____]
(optional) [And ______]
(Line #3) I should ______
You will create tickets in your project management tool like Jira, Pivotal Tracker, ClickUp, or Notion. Each ticket is a collection of many stories. Together, they encompass the smallest possible unit of work, sometimes called a ‘minimum viable product.’ It is the least amount of work we can deliver to have something that can be demoable.
Whereas most scrum teams use “1 story per ticket” I do not recommend this.
How large or small should a ticket should be?
The answer is always the same: The ticket should be as small as possible to deliver one unit of discreet work. There is a school of thought in scrum that each ticket must be infinitesimally small to force the software work to be iterative.
I do not subscribe to this ideology because splitting tickets into infinitesimally small units of work takes the iterative approach to an extreme that isn’t useful. Developers can still deliver iteratively even if the ticket isn’t written iteratively.
(Developers can — and should — break up one ticket into multiple pull requests).
Each pull request can represent one small discreet unit of work, but it still requires several pull requests to complete the whole story or complete feature. I generally prefer that approach because it lets the developers make the call about how to split up the work in the moment. The story writing process doesn’t artificially create units of work that are too small to make sense, which is the danger when the Product Owners start to break things down too small.
The flip side is that tickets can get too large. However, it is preferable to start with large ideas and then break them down naturally during the process. I recommend each ticket have between 2 and 10 stories within them. (Remember, each story is just the 3, 4, or 5 lines from the template.)
For all features you will write, always write in story form. Each story should be 3-5 lines long. Start with these 3 lines:
(Line #1) As a ______
(Line #2) So that I can ______
(Line #3) I should ______
#1 is the who; line #2 is the why, and line #3 is the what and how.
If Line #2 (“so that I can”) needs clarification regarding what the actor is doing, you may use the optional lines of “When____” and add more context with “And___.”
Each line has a specific purpose, and you should focus on sticking to the purpose of the line.
Line #1: As A (The Context Actor)
In software, we talk about the context actor for the feature or feature set. A context actor simply means the customer, the admin user, the visitor, i.e., the person who is going to use the software. It does not mean the developer, the product manager, or the CEO. This is one of the most common mistakes I see: without knowing how to correctly describe the context actor, product owners use arbitrary ideas as the “who” of the story.
The context actor is very important because this is the bridge to domain context interaction, which is a fundamental part of large application design. (We actually write the code very much considering the context actor which is why getting it right is so important.)
Don’t write stories that begin with “As a developer.” That’s an abuse of story form. You shouldn’t make the context actor an external “service” or another computer program (like, “as a client app” or “as an external API”). This too, is an abuse of story form. If you find yourself doing that, stop and ask yourself to interrogate the story. (See below, “When a Story Isn’t a Story”)
You should also be careful when specifying the context actor as the company’s CEO, yourself, other product owners, or other team members in the company who don’t directly use the software itself. The only time you should use members of the company as context actors is when they are directly using the software that is going to be built. (For example, “as a customer service agent” is a good use case if and only if you are building a feature specifically for customer service agents.) If you’re building a dashboard for your marketing team or executive team, it’s OK to use “as an admin” or “as a marketing manager.” You should only ever do this if that person is really the actual person who will be interacting with the feature, not merely whom the request came from.
This is the single most abused facet of story form that I see.
The “As a” line is the who.
Line #2: So That I Can ____ (The purpose for the interaction)
The purpose of this line is to force you to think about, talk about, and communicate why the actor is doing the thing they are doing.
This is not the desired outcome. This is why the person is taking the journey. If the chicken were crossing the road, the “So that I can” would be “to get to the other side.” The fact of the road’s size, the traffic, whether the the chicken sees the stop light (probably not, because he’s a chicken), and whether the cars will stop for the chicken. Those are all what and how. The “So that I can” should strictly be the why.
This too, is open for abuse. Don’t let ‘the who’ bleed into your why, and don’t put the desired outcome here in the ‘So that I can’ (that’s the I should part).
Line #3: I should _____ (The Desired Outcome)
Finally, the I should part explains the desired outcome— or the what and how. Typically you will always write things here that the user will actually see on the screen while using the software. If that’s not possible, you can use different language here to discuss the database or backend state. (Like, “I should have my changes saved.”) but that should be avoided whenever possible.
I should is the purpose for the story’s existence. After you’ve written the 3 standard, required lines, ask yourself this question:
Can I remove line #1 (As a) and line #2 (So that I can) and still basically get the idea of the story? If the answer is yes, then you’ve successfully written a good 3rd line (I should). If the 3rd line makes absolutely no sense on its own, consider adding more to it. For example, “I should be successful” is not as useful as “I should be logged in” or “I should see a message telling me my record was saved.”
You should tell us what the user is being successful at or how the software behaves. Spell it out even if you think the people you work with know it already.
That doesn’t mean you should actually leave off the 1st and 2nd lines— quite the contrary— just that the 3rd line needs to be descriptive enough to convey the what and how on its own. (Albeit, missing the context that the first two lines provide.)
When & And (Additional Info Before I should)
If you’ve written the 3 lines and you look at your story and it’s a complete idea, stop there. If, on the other hand, it is missing context, you should then add more lines before the 3rd line:
Here you will add additional context if and only if necessary. Don’t go overboard. “When” and “And” lines should be things like steps that need to be taken to get the user in the right place or screen, prerequisites that must be met, or setup information important enough to include but not the actual result or desired outcome. Include additional lines only when necessary.
Stories should be lettered or numbered: Story 1, Story 2, Story 3. Each story should describe a new facet of the implementation, but doesn’t need to repeat things for the sake of repetition. For example, if the story might apply evenly to all states of the application, you don’t need separate stories for each state. On the other hand, if different states cause different results, then you do want different stories to describe each variation in result.
By the time we get to the end of all the stories you’ve written, it should be clear what the entire feature is doing: The “happy path” (or cases when everything goes right) and the “edge cases” (or cases when things don’t) both get described. The reader (developer) has a good sense of all the things that the ticket is trying to achieve. Nothing is left hidden or missing. No additional context is needed to implement the feature— everything is described in the totality of all the stories you’ve written together (that is, all of the ones for the feature or ticket).
Full-Stack Stories (“frontend only” or “backend only”)
Story form comes from the days of full stack software development. It doesn’t make a lot of sense in siloed teams and siloed-stack engineering. For example, it doesn’t make sense to write a story for just the backend or just the frontend. The story must communicate from the customer’s perspective, and the customer doesn’t care what code lives on the frontend and what code lives on the backend.
When a Story Isn’t a Story
Sometimes you are doing simple copy changes. For those, I don’t use story form. Also, for bugs that have a stacktrace, I also don’t use story form. Instead, I prefer just the stacktrace, or if the bug is reproducible, the steps to reproduce with “Expected result” and “Actual result” to describe the bug and what should be fixed.
Sometimes you do things that have no users, so you can skip the story form.
The most problematic aspect of software, codebases, and development process is inconsistency. Inconsistency creates cognitive friction that costs your team time and money.
Keeping all the Product managers and Product owners consistent about story writing is one of the strongest and most important things you can do to lay the foundation for success of your scrum team.
With a little attention to consistency and getting it right, the payoff becomes exponential. With the right mindset and a disciplined approach to doing it the right way, you will reduce friction and create joy for your team and teammates.