This article is for software builders, particularly those who work on UI/UX for large user bases! It explores the concept of UI/UX thrash, its negative impacts on users, and how to build empathetically and intentionally to decrease thrash.
It’s about a 15-20 minute read; thanks for reading. 🙂
Imagine that it’s Sunday, and you’re going to a diner you’ve been a regular at for years. You order your usual burger, and then it shows up…with mayonnaise…an ingredient you detest that wasn’t there before. The menu’s totally changed! Now you realize you need to pay more attention to the menu changes, and your relaxing Sunday routine now requires some extra mental energy.
Then, the tables get rearranged and your favorite spot with the right lighting is no longer there. They redecorate the place, and you’re not so in love with the vibe anymore, and the music feels just a little bit too loud for your liking.
Over time, as you encounter more and more these changes, your love of the restaurant slowly withers. These changes might not even be negative for other people, and the Yelp reviews from new customers might even be getting better, but your trust and love has degraded. You stop recommending people to the diner, as it’s no longer the place you once loved.
Meanwhile, the restaurant owners might be thinking, “Ooh, we’re doing so well with our new changes! We’re even getting more customers lately! Maybe we should change even more things!”
(This hypothetical is purely fictional, but I truly do not like mayo 😛.)
Modern software products change a lot more than at restaurants, especially in early stages. Restaurants, like software, also have user interfaces (UI) and experiences (UX).
If we’re lackadaisical about making these changes all the time, it’s like re-arranging the restaurant floor and the menu every single month. Many people might not notice or comment on it. But over time, if small, poor experiences are had repeatedly, it contributes to a cumulative negative experience that doesn’t bode well for our products or our restaurants.
This doesn’t mean you, the developer, should fully cater towards a conservative part of your user base who may not want any change, but we can build software in a way that massively reduces negative experiences for all kinds of users involved, and often even helps us build faster and more reliably.
Being a good UI/UX developer means being an empathetic builder, being able to predict and measure how users will respond to the changes in your product, and to sequence and design changes in a way that reduces the overall UI/UX thrash.
What is UI/UX thrash?
How I define UI/UX thrash (or disruption) is when new changes we build into the product disrupt users, because their expectations do not align with how the product behaves.
This could be because of:
- Behavior changes: We change product behaviors, business logic, or move things around without users being able to easily discover or learn these changes.
- Bugs: We introduce bugs that prevent users from reliably completing flows they expect and we hurt the product’s overall reliability.
- Performance: The software degrades and slows down users from going through flows as quickly as they used to be able to.
- Friction: We’re otherwise adding friction to the user experience or user interface in a negative way.
Commonly thrashed UI/UX includes: content (any text), keyboard behavior (shortcuts, tabs, navigation), accessibility behavior, i18n (internationalization) and l10n (localization), help content, and developer APIs.
We as developers might be:
- Building what we believe to be new, better products and features.
- Fixing behaviors we believe to be incorrect or inconsistent.
- Testing out different experiences to decide which would be the best one to finalize.
From our point of view, we might think the user behavior before was wrong, and therefore users are wrong for liking it. That doesn’t at all change the fact that we introduced UI/UX thrash and a negative experience that adds up.
Examples of thrash
Previously, I worked on Facebook Profiles. I currently work at Notion. Here’s some examples of user sentiment around thrash looks like at both these places.
At Facebook
At Notion
Notion is a productivity app for your life’s work — it provides a bunch of building blocks (like docs and databases) to help you organize just about anything. I work on Notion’s databases. Notion, like any other apps, has its fair share of UI/UX thrash as well.
As Notion grows in the creator ecosystem, and entire applications and libraries are built on top of Notion, it becomes increasingly imperative that UI/UX (and API) thrash is minimized.
These changes and negative sentiments above do not represent the vast majority of users’ experiences! And every app has both user thrash and dissenters. But disrupting and losing users is never a desired outcome if we can avoid it.
Negativity adds up faster than positivity does.
One may ask, “so what? it’s just a few minor bugs and they’re not that big of a deal!”
Unfortunately, humans notice negativity and change far more than positivity and consistency.
Once someone notices one flaw, they’ll often start to notice many more. Over time, all these little bugs, performance issues, and behavior changes accumulate and take a toll on user sentiment towards the product. Many will begin to ask, “Is [X] getting worse, or is it just me?”
Negativity begins to spread like wildfire, in the form of public reviews or private word-of-mouth. The 1-star reviews are paid far more attention to by prospective users than the good reviews. This occurs in every industry, from service, to commerce, to software. Reputation sticks.
Your mistakes often cost you more than your shiny new features win back.
When you introduce thrash, you’re introducing negative experiences, multiplied by the number of people who encounter them.
- New feature rollout moves buttons around for an existing task x 10,000 people confused to where the old flow is x 1 minute figuring it out = 166 hours of wasted time & lots of confusion
- Bug where a task is slowed down for 5 seconds x 10,000 people encountering that bug x 5 times per week = 69 hours of wasted time, every single week & lots of annoyance
Facebook was thrashing daily users in the tens to hundred of millions in its product development cycle, which significantly hurt its love and trust over time. 💔
It’s extremely hard to measure the impact of thrash by data analysis, since they accumulate from many different changes and have long-term, deferred impacts.
As a proxy, we can measure fixes to thrash (which should be done rarely, as this hurts product quality for the sake of measurement).
At Facebook, a bundle of reliability, quality, or performance improvements that took hours or days to build would often have more statistically significant wins in top-line metrics than features that took months to build.
Why didn’t people work on these improvements more?
My answer: Incentives and culture. Bug fixes, polish, performance improvements, and reliability, are perceived as less impactful and valuable than new feature development for one’s career. PMs have to keep proposing new features and projects, and the product development engine needs to keep going. New features are easier to quantify and sell to leadership.
Finding the right improvements to tackle and tackling them also takes a lot of practice! It’s different than feature development, and folks didn’t practice it. Roles like Product Specialists existed just to help find the low-hanging-fruit reliability & quality problems but many major problems were often unaddressed.
Thrash affects people differently.
Throughout using a product, every single user builds expectations and knowledge over time. They come to know where certain buttons are, how to navigate through menus, or what specific icons mean. But thrash affects every user differently.
Types of people whom thrash affects less:
- Technically literate users (correlates with younger age)
- Casual users who don’t use the product much
Many users fall into this category! Most small-to-medium-sized UI/UX changes will go completely unnoticed, and users might not have any notable negative sentiment towards them.
Types of people whom thrash affects more:
- Less technically literate users (correlates with older age)
- Expert users and new, learning users
- International users who aren’t in the product’s primary locale
- Users who rely on reference content (videos, tutorials, books), much of which are made by external creators
- Neurodivergent users (e.g. with ADHD, dyslexia, autism)
- as someone with ADHD, UI/UX changes can be extremely jarring 😔
- Users with disabilities, perhaps relying on screen readers or keyboard / mouse-only navigation, or taking much more time to do tasks (e.g. Parkinson’s)
When you’re a daily user of a product, you’ve likely developed strong habits and reliance around the product behaving the way you understand it behaves. Any major behavior change, performance slowdown, or bug massively hurts your productivity.
Imagine if Windows suddenly changed Ctrl+C/Ctrl+V to no longer copy/paste or if loading any app took an extra 200ms!
Additionally, expert users disproportionally drive new users to the platform, by creating content or reviewing the product for others. If you erode their trust and love, you’ve lost the largest promoters of your product. These same users are often technical enough to migrate their entire workflow to another product, bringing along others with them.
At Facebook, thrash would occur to important creators all the time — whether it was the massive changes like the view count definition — or just day-to-day confusion as to where important flows were moved. I watched Harry Mack, a rapper who with billions of video views, struggle finding very basic flows on FB Live due to UI/UX thrash. Facebook struggled to retain creators all the time on their platform (for many other reasons too).
If your primary creators and power users leave the platform, the community and the value to regular users also gets hurt drastically. The long-term impact by user thrash is not captured by short-term metrics.
Build an exceptional product, and keep it great, and you’ll win the fruits of your labor over time.
Great products disappear into the background.
Audience member: “Do you have any advice for artists who want to be more productive?”
Cory Wong: “…I try to relieve as many barriers as possible on the logistics side and the technical side. So I am very proficient in Pro Tools, Logic, engineering, and mixing. So that way, when I sit down to do something, I’m not worrying about “what’s that hotkey to do this?” and all of a sudden, my mind has diverted my attention and creativity from the artistic idea to this technical thing. That all needs to be 100% in the back of my brain, so anything that I need to do in the programs, is completely second nature, and the software is a part of me, so it just disappears into the background and I can focus only on the art.”
11/12/2022, The Warfield (concert I was at!)
When software behaves as we expect it to, due to a combination of:
- Discovery: Features and changes are discoverable and learnable.
- Design: UI/UX behaves in an intuitive, well-designed, expected way.
- Knowledge: Time learning how the software works can be applied fully.
- Reliability & Performance: Software is dependable and meets our expectations of speed.
The software disappears into the background, and users can get into flow states and just focus on their task at hand.
“Good design is actually a lot harder to notice than poor design, in part because good designs fit our needs so well that the design is invisible” — Don Norman, The Design of Everyday Things
Every occurrence of UI/UX thrash or lack of user ↔️ software expectations alignment brings the software to the forefront again.
Imagine if while Cory Wong was using Pro Tools, and the keyboard shortcuts he was using suddenly changed after an update, or settings he was looking for moved to different places, or a key workflow suddenly became super slow. That thrash would certainly hurt his productivity, and he’d probably like the software a bit less each time he hit one of these experiences.
How do we reduce UI/UX thrash?
Ok, let’s not overcorrect and spend all our time bogged down in testing and worrying about thrash that we don’t get anything done. Features are important!
But there are some huge opportunities here, with investments in time and education, for a much more reliable, consistent, loved product. With the right balance, we can be both short-term and long-term minded here, and win in both fronts.
All this advice is contextual — it depends on where you’re at as a company, what the state of your software and design systems are, and who your audience is.
Building high quality UI/UX takes craft and lots of practice! Trade-off management is key.
The ideas below are all toggle-able. I recommend you toggle through the first two.
#1. Slow down product development and decision making in the short-term. Build systems and principles instead of one-off decisions and short-term architectures.
Paradoxically, this will also make designs and decisions faster in the long-term.
Slowing down makes you faster? Yep, you read that right.
When we have short-term decisions and build short-term answers, we’re often creating more debt and complexity for us in the long run. Instead, we can regularly ask ourselves, “Is it possible for us to the larger class of problems instead?"
Buckle up; this is one of the most important of the 5 ideas, and the longest one.
Case study: Action Menus
Let’s consider this a user action bar that looks like the below buttons and menus.
Note: this discussion is purely hypothetical and manufactured for this article. 😅
Each day, millions of users use these buttons and menus for acting on user profiles.
For a few years, we’ve lackadaisically added more actions into the menu, deciding on a case-by-case basis where they should go.
Over the course of feature development, we might be moving actions around and in and out of this action bar. We also may have never settled on how to decide which button is highlighted blue. This happens from multiple different teams for years optimizing for different goals, and the action bar changes, over and over, thrashing users.
Every single time we move these buttons around or change the behavior, thousands to millions of people might go, “Where is my activity log?” or “How do I add a friend?” and spend extra time on this task or never figure this out. And 95%+ of these folks are never going to tell you this in any way.
All of these little decisions and changes take significant time and effort. On our side, as we make these changes, we’re also dealing with a different kind of thrash — to developers, designers, and product managers in dozens of meetings and code changes.
We can reduce this thrash by building product principles and design systems that solidify decisions that achieve a good enough result.
In an ideal world, we’d have come up with these answers early on, before any action bar code was even written, so we don’t have to rewrite it.
But let’s say we don’t have the luxury of foresight.
We could start by creating a clear, consistent design system for the buttons (font-size is 15px, buttons have a border-radius of 6px, uses #1B74E4 as a background, etc.).
We could have a few discussions with relevant stakeholders and then come up some with principles like:
Our action bar and overflow menu principles are:
- The 1st button is the primary “connection” button on non-self (other peoples’) profiles. The 2nd button is the primary “engagement” button” on non-self profiles.
- Additional buttons go into the “overflow” menu, ordered based on proximity to the Profile surface, and daily active users of the surface it goes to.
- The blue button highlights “engagement” if users are already connected, or “connection” if they are unconnected.
- … and many more.
We could establish a documented cross-functional org process for other teams to add new actions to the surface, and that engineers and PMs must review actions that other teams want to add.
We could enforce these principles and designs in the code via core, reusable components and code architecture, and now save hours of engineers creating their own, inconsistent custom components each time.
All these principles and systems should be based on well-informed debates and discussions, powered by past data analyses, UX research, design intuition, and process pain points.
- For example, through data analyses and research, we may have learned that the first button gets a +XX% click rate, the highlighted button gets a +YY% click rate, and folks are having a tough time finding out how to connect (add friend, follow) with other users. We then used this knowledge to come up with the systems above.
Now, we’ve made decisions and structures to reduce decisions and work down the road, and PMs, designers, and engineers rejoice! All those ad-hoc questions and meetings about ordering and coloring are now no longer needed. Over the course of a year, we’ve saved thousands of hours and made our product more consistent.
Later, we might change these principles to suit different needs, but hopefully any principles we make can hold across a long period of time.
💡 Additional idea: Solve the problem at different levels or problem spaces.
We might even share these principles with other surfaces (like Groups and Marketplace) for app-wide consistency — because it seemed to work great for Profiles!
But, as we start thinking this through, we may realize many of our principles and systems may not fully bode well for this larger problem space.
An alternative route is that we could’ve started solving the problem differently at the beginning:
Vertically: starting at a different scale and going top-down, like at the org or company level.
Horizontally: tackling a different problem space, like improving button or menu design consistency and behavior across the app, or cross-functional collaboration spaces.
All these routes have different trade-offs, complexity, and staffing requirements! It’s up to you to decide how to best solve different classes of problems.
The principles and systems we came up with may not be fully optimal for a given use-case, but that’s okay! It’s impossible to have a fully optimal system anyways, as every choice has different trade-offs.
Don’t let perfect be the enemy of good. Consistency helps users build knowledge and expectations about the UI/UX and trust that their concepts hold.
Caveat: This cultural shift is hard to implement at first, and there may be significant friction to making such impactful changes at once. Implementing the changes we decide on also will cause UI/UX thrash in itself. And our hand could be forced with new requirements over time!
This result is totally possible and I’ve seen it play out many times:
Or this:
As we start building systems, we need to build them to be able to scale with changing requirements and organizations, with careful research and design intuition, and execute in a way that works for our organizational culture.
As we do more of this principle & system-based development, we get better at it! We get better at building scalable architectures, documenting principles, designing systems, establishing cross-functional processes, discussing trade-offs, and landing on optimal product behavior.
Suggested read: The Pragmatic Programmer.
#2. Test via dogfooding, automated testing, and/or betas before a full scale release.
Dogfooding means using your own products — ideally, trying out many different use-cases, including how your own users would use them.
There’s often a tendency for engineers to push out features as quickly as possible. They want to see the impact of what they’ve built immediately. Product teams may feel confident that they can resolve bugs within a few days, or that metrics or alarms will tell them what they need.
Unfortunately, this way of thinking is often lackluster for building quality products at scale. By releasing changes immediately, we’ve let the cat out of the bag, and tons of users are getting used to UI/UX flows or exposed to bugs and reliability issues.
Even just letting employees or beta testers test these changes for 2 weeks, you may find significant feedback that makes you want to change many different behaviors. You can then prioritize and solve all the notable feedback and bugs before a real production launch.
Automated software testing: We should also spend time building automated software tests (end-to-end, screenshot, integration, or unit tests). Engineers can further contribute to the overall software testing culture at the org or company, by documenting how-tos or contributing to testing infrastructure or promoting good practices, to get everyone on board, and make it as easy as possible for others to write tests.
Both these solutions are often better than putting out the feature to everyone, THEN slowly getting feedback or bugs, THEN making changes later. The UI/UX thrash for a production behavior change has multitudes of more impact. Testing saves a ton of time and context switching down the road.
Caveat: Keeping something in beta does lead to a bit more context switching, and slightly slower release cycles, but it minimizes the thrash and leads to better outcomes. You also need to set up your betas in a way to get sufficient qualitative or quantitative feedback, which can be burdensome. And automated software testing is an art in itself — managing trade-offs between time, reliability, and stability.
#3. Run more thoughtful, empathetic experiments.
If you work at any large-sized tech company, chances are, the company runs many UI/UX A/B tests, or even some tests with 3+ variants.
When you get so used to running A/B tests for each feature iteration or little UI treatments, you might forget that behind each metric, there’s a person encountering the experience as each of the “test” or “control” units.
Experiments are incredible tools, but the cost is non-negligible to both users and codebases.
During my time at Facebook, teams would often change the entire navigational structure or information hierarchy for major surfaces in an experiment…and then revert it…and then do it all over again. Some unlucky users could have 3+ totally different ways to navigate some critical surface over the course of a month. 😔
This was all in service of informed decision-making and testing MVPs to rapidly iterate, but I think the insights we gained were not worth the cost to users. This cost will never be measured, because data analysis doesn’t measure the thrash induced by the experiments themselves after they’re turned off.
We can run more empathetic experiments by putting our best foot forward (backed by UX research and design intuition) and limiting the number of variants and exposure sizes for key flows. We should make sure that folks are gracefully transitioned out of old experiment states, so folks aren’t stuck in less optimal states. We should carefully research past experiments and record results of new experiments, so we don’t get stuck into experiment loops where we run the same tests over and over.
Experiments are ideal for flows that the user will only encounter once, like signup or onboarding flows, or invisible UX elements, like performance and reliability improvements. These scenarios produce the least user thrash.
In these experiments, there’s a lot we should pay attention to if we can, like performance and reliability metrics, maybe that’s the startup app time, or bugs/crashes per 1000 users.
Experiments cost time in the data analysis, in the change management process, and the code wrangling. If we run fewer, better, careful experiments—valuing quality over quantity—we’re saving time and making our UI/UX much less confusing.
#4. Consider bundling multiple changes.
Sometimes bundling multiple UI/UX changes at once can soften the blow. The user may recognize “oh, this is a re-design” and actively pay attention that many things are changed, instead of just running into little hurdles one at a time. They might not interact with the product with the exact same expectations they had before, because they know (consciously or unconsciously) that there’s a slight re-design and may be more receptive or aware of changes.
Bundling also can be used to create consistent system behaviors across the board all at once. For example, if you were changing a keyboard shortcut in one place, you should probably change it everywhere.
Software development used to almost always be bundling at a large time interval. Releases were closer to quarterly or yearly than daily, and often releases would be a whole new bundled version (think: Microsoft Office 2008 → 2009 → etc, or Windows XP → Vista → 7).
Nowadays, the norm for web development is daily release cycles, and major bundling is rarer for most west coast SaaS companies.
Caveat: Bundling at the right granularity is hard to figure out and execute well! Bundling carries with it more costs: more execution and design time. Bundling also makes the changes more apparent and requires some mental effort from the user to adjust to all the changes at once, whereas a minor change might have been unnoticed by many. Deciding to un-release a bundle of UI/UX changes is ultra thrashy!
#5. Consider onboarding, education, or communications for UI/UX deltas introduced.
For some changes, it’s great to smoothly onboard and educate users, or announce them publicly. Users might be excited by the new feature or frustrated by something that they can’t find, and onboarding or education helps!
For many changes, it’s unnecessary. We don’t want to end up with a product with tooltips everywhere, or have folks go through a dozen popup dialogs each time they use the app. Folks are already bombarded with attention lever abuse.
It’s a tough balance — balancing user attention with education and positive user outcomes.
One possible set of system principles for actions to take could look like:
Type of change | Possible actions | Factors to consider |
New feature | - Add a soft “new” badge to the feature that clears immediately.
- Add a short (time-based or impression-based) onboarding dialog if it’s a complex feature.
- Build new help center content around helping folks understand it.
- Announce new features in a consistent location (patch notes). | - Complexity of feature
- Discoverability
- Expected usage |
Changing existing product behavior (e.g. moving things around) | - Update help center content around helping folks understand changes.
- Announce behavior changes in a consistent location (patch notes).
- Add a quick one-time signifier to indicate where new flows might live. | - UI/UX delta from old experience
- Friction added
- Discoverability
- Past usage |
Improving performance & reliability | - Call it out in patch notes — acknowledging that people’s concerns were valid, and letting people know it’s better now! | - Delta of improvement
- Usage / importance of flow |
This all depends on your app and many other factors! It’s easy to overwhelm folks with signifiers, and tricky to balance right.
We may also decide on additional tooltip principles like: (1) Only show tooltips for critical privacy or curation changes, or navigation changes where the friction added is significant, even for a power user. (2) Never show more than 1 tooltip at once. (3) Tooltips will only show up for 4 weeks after product release.
We might also build a framework that makes making these new user experience indicators super easy.
Caveat: Many people will totally ignore most classes of these signifiers, and never read product updates! Balancing the right attention levers and catering comms specifically for different user archetypes is key here.
We’re managing tradeoffs here: time & cost to implement vs expected negative impact, user confusion, or improved product usage.
None of these five points are fool-proof, but they can be generalized to two directives:
- iterate on the meta of product development: answering the question, “What are the tradeoffs of our current product development cycle & how can we build better?” and raising the product quality bar.
- practice user empathy: answering the question, “How can I put myself into the shoes of users at scale and predict, understand, and measure the impact we’re making?”
In this quest, we’ll often try new things that don’t work out or feel like we took one step forward and two steps backward. That’s okay — c’est la vie. 😊
Some thrash is inevitable.
None of us have a crystal ball with a perfect roadmap, with optimal designs and systems with every detail perfect. Decisions, designs, and visions change over time, and it’s great that we are able to evolve products in response to new information like changing user requirements.
Some thrash is inevitable for us to evolve products and not have to work around massive design constraints. People don’t always love change, and we can’t overly cater to that.
But all users do care about consistency and usability, and helping align their expectations with our product outcomes is massive for love and trust.
With more intentional decision making and development, we can do thrash users less and building products that are loved and trusted by users.
I hope this article helped you in your journey to do so! 😊
Thanks for reading!
If this topic interests you a lot, I’d recommend checking out 📖 The Design of Everyday Things by Don Norman.
Much of this article is inspired from this book, my love for design, and my experiences as a full-stack engineer.
Further reading:
- Unchecked AB Testing Destroys Everything it Touches by Derek Zumsteg
- 📖 The Pragmatic Programmer by David Thomas & Andrew Hunt