The Happy Path Is a Guess
Did you know that before a cooler can be sold as bear-resistant, it has to spend an hour with a grizzly?
The Interagency Grizzly Bear Committee has run this test since 1989. Testers bait the product with peanut butter, put it in the enclosure, and start a clock. Sixty minutes of biting, clawing, and chewing. If the bear gets the food, the product fails. One bear in particular, named Kobuk, was very good at his job.
Kobuk had a knack for finding inventive ways to break into coolers, destroy garbage cans, and generally wreak havoc on any new product put in front of him.
When we build software, we rarely consider Kobuk. We build for the person who fills in the form the way we pictured it and clicks the buttons in the order we laid out. Then users show up with their own data and goals, and the cracks start forming.
How do you build for resiliency when you can't always know how your software will be used?
Users Don't Have to Be Clever to Break Your Software
Christopher Null spent years unable to sign up for things. He would type his last name into a form and get an error saying the field couldn't be left blank. His brother, his wife, and his kids all had the same problem. He wrote about it in Wired in 2015 after two decades of frustration.
Null was not probing for weaknesses. He typed his name.
In 2010, Patrick McKenzie published Falsehoods Programmers Believe About Names, a list of forty assumptions that show up constantly in production systems. People have exactly one name. Last names are at least two characters. Names do not contain numbers. Each assumption is wrong, and each one sits in validation logic across millions of codebases because someone pictured a user who looked a lot like themselves.
That is most of the failure surface customers experience. Not attackers, and not power users doing something exotic. Just a use case that wasn't considered.
Kobuk had one hour and a jar of peanut butter. You may have millions of people using your software every day, amassing tons of hours poking at your application. Given that much time, ordinary people find just about every crack in the system.
Avoid Focusing on the Happy Path
Very few engineers would argue with any of the above. Teams constantly choose to ship the "happy path" version of their software every day.
The story describes what the feature should do. The acceptance criteria describe the same thing as a checklist. The demo walks the working path. The estimate covers that path, because that is the only path anyone wrote down.
So the duplicate submit, the four thousand pasted rows, and the apostrophe in the last name all surface later, usually in code review or QA. Raising the issue means asking for unplanned work against a deadline someone already promised, so it gets logged as a follow-up ticket that never gets picked up.
Slowing down feels impossible.
But the cost is real, even if it gets overstated. Boehm and Basili's Software Defect Reduction Top 10 List found that fixing a problem after delivery can cost up to 100 times as much as fixing it during requirements and design.
|
|
Where can AI save you time?
My friends at Big Creek Growth put together a quick survey to spot the repetitive work you can hand off to automation.
|
|
Find Out How People Are Actually Using It
You already have a record of users doing things you didn't plan for. It's in the support queue, the on-call pages, and the session recordings for the part of the system you're about to touch.
Before starting a feature, spend twenty minutes reading tickets filed against that area. You're not looking for bugs to fix. You're looking for what the person was trying to accomplish when they hit the wall.
A ticket that says "import failed" gives you nothing. A ticket that says someone pasted four thousand rows from a spreadsheet, waited, saw no feedback, and hit submit again tells you about a timeout, a missing loading state, and a duplicate-record problem. One of those is a validation issue. The other two are about what the software told the user while it was working.
Watching someone use it is better still. Nielsen and Landauer's model, the basis for the five user guideline, puts a five-person session at around 85% of a design's usability problems.
Later work by Laura Faulkner showed the real range is wider, anywhere from 55% to 99% depending on the group. The spread is worth knowing, but it isn't the reason to do this. The gap that matters is between zero users and a few, and most teams sit at zero.
You don't need a research program. You need to watch five people try to finish the task and write down every place they hesitate.
Put the Failure Cases in the Story
Knowing how it breaks does nothing if the work never gets budgeted.
The failure cases have to be in the acceptance criteria before anyone estimates, written the same way as the rest of the criteria. Something a reviewer can hold you to. "Show a specific error when the file is larger than 5MB" is criteria. "Handle errors gracefully" is a wish, and it will be cut without anyone noticing.
That means naming the behavior, not just the guardrail for what the user sees when the upload is too large. What happens on the second submit. What the screen does during the eleven seconds the import is running. Most support tickets aren't caused by a missing check; they happen when the software goes quiet, and someone makes a reasonable guess about what to do next.
The security half is the same conversation, with higher stakes. The 2025 CWE Top 25 was built from 39,080 CVEs disclosed over a single year. Cross-site scripting ranks first, and SQL injection ranks second. Both come down to trusting input that came from outside the system. Validation isn't a hygiene item near the bottom of the list. It's the top two.
None of this requires better story writing than you already know how to do. It requires writing those lines down while the work is still being scoped, when adding them costs a conversation instead of a release.
Resistant, Not Fail-Proof
The IGBC will not call anything bear-proof. Their own certification page says so directly. Sixty minutes, not forever.
The pass criteria are more forgiving than you'd expect, too. A container can come out of that enclosure punctured, scratched, and bent and still pass. For food storage, holes up to a quarter inch are fine. Damage is acceptable. Access is not.
That's the judgment call this whole thing rests on. You aren't trying to build something no user can break. You're deciding how long it holds and which failures you're willing to take.
Most of the time the ranking is frequency against what it takes down. A cosmetic glitch a hundred people hit every day is annoying. A silent write failure two people hit a quarter is worse, because nobody finds out until the data is wrong and there's no record of when it started. The second one goes in the story. The first one goes on the list.
Say that part out loud when you write the criteria. A team that has decided which failures it accepts can defend the ones it chose to handle. A team that never had the conversation ships whatever they happened to think of.
Kobuk never had to be clever. He had time, motivation, and no preconceived notions of how best to use the product.
Your users are in the same position. They aren't trying to break anything. They're trying to finish something, with their own data, on their own deadline.
So take whatever you're shipping this week and write down three ways someone finishes the job wrong. Not exotic ones. Pasting from a spreadsheet, the double-click, the name that doesn't fit the field. Pick the ones that would actually cost you, and get them into the story before anyone puts a number on it.
That's the whole difference between software that survives contact with real users and software that comes back two weeks later.