Removing a feature is a feature
Features aren’t what make a product great. Being the best at solving a particular problem does. Every time you remove a feature that doesn’t support your product’s core use case, you’re actually adding an implicit feature that does.
Ultimately, your users use your product because they’re trying to solve a specific problem. It could be getting from point A to point B, finding their next romantic interest, or having some place to store their vacation photos. Whatever reason, they have a specific task in mind, and your product is simply a means to an end. That means that every “nice to have” feature that doesn’t solve the problem they’re trying to solve, isn’t just product cruft, it’s actively standing in their way.
Features aren’t free
Features come with a very real cost to users. As I wrote a few months back:
We have a motto at GitHub, part of the GitHub Zen, that “anything added dilutes everything else”. In reality, there is always a non-zero cost to adding that extra option. Most immediately, it’s the time you spend building feature A, instead of building feature B. A bit beyond that, it’s the cognitive burden you’ve just added to each user’s onboarding experience as they try to grok how to use the thing you’ve added (and if they should). In the long run, it’s much more than maintenance. Complexity begets complexity, meaning each edge case you account for today, creates many more edge cases down the line.
The WordPress community has a similar philosophy, “decisions not options*.” Every time you provide a user with an option, you’re asking them to make a decision, and those decisions quickly add up, especially when the user doesn’t care or doesn’t fully understand the implications. Ultimately, many of these decisions are technical or domain-specific decisions, and as a project maintainer, as the subject-matter expert, it’s your obligation to absorb all that complexity on behalf of your users, not to simply kick the decision can down the line.
With every new feature you add, users will need to go through that learning process all over again, not to mention, that new knob you added for User B, because “why not?, it’s just one knob”, is going to make it harder for User A to find the knob they’re actually looking for.
There’s no such thing as declaring “feature bankruptcy”
Even though we often call it “technical debt”, sadly, there’s no such thing as declaring “feature bankruptcy”. Every feature you add creates an implicit contract with your users that you’re going to support that feature in perpetuity. That means that every dependency update, every redesign, every refactor, becomes exponentially more complex with each new feature, as you have an ever-increasing list of things that you must now support, and this technical debt quickly adds up to create a perpetual engineering tax on feature development in the form of ongoing maintenance and backwards compatibility.
Product debt isn’t a foregone inevitability. Chances are, users don’t need quite as many knobs as you think. Research suggests that 90% of users adjust fewer than 10% of settings, with the majority of users changing at most, about 15% of configuration parameters for any given piece of software. That means that upwards of 80% of settings shouldn’t even be there in the first place. Rather than slowing marching your product’s settings page towards eventually resembling the complexity of a space shuttle cockpit, you should have the discipline to build features that support your ideal use case (and only your ideal use case).
Unfortunately, once a feature’s been added, once it’s in the hands of users, whenever you make a change, regardless of what the change is, a non-zero number of users are going to complain that the change broke their workflow. Thus, the easiest way to avoid upsetting users is often to prevent the feature from being added in the first place.
Playing feature goalie
Absent your intervention, projects have a tendency to become feature Christmas trees, with each stakeholder adding their own domain-specific ornaments. This happens for several, easily avoidable reasons, at least if you can learn to spot them ahead of time:
Being reactive to ad hoc requests - customer feedback is invaluable, but your users are experts at using your product, not at building it. A one-off feature request that might satisfy a single user, might not be the right move for your product in the long run, especially if they’re not your ideal user. Avoid the temptation to play feature whack-a-mole. Instead, make your taste, vision, and foresight a feature in and of itself, building products that proactively solve your target users’ needs, before they know they have them, rather than reactively implementing a patchwork of individual features to satisfy your loudest users’ complaints.
Scope creep - projects have a natural tendency to drift towards solving problems beyond their original purpose. Once you’ve got the 0.1 that tackles one problem, it’s all too easy to start seeing related problems that could be tackled in similar ways, albeit less well. If your e-reader has an internet connection, you might as well add a monochrome web browser, right? When problems are similar but not the same, your product becomes sort of good at lots of things, rather than being the best at the thing your users want to use it for. Not to mention, there’s an opportunity cost to developing that other feature. Define the scope early on and purposefully revisit that discussion wholesale before agreeing to tackle any feature beyond your predefined problem space.
Scratching a technical itch - Technology can often make new user-centric functionality possible, but some of the highest impact features are also some of the most boring to implement technically. Borrowing another phrase form GitHub Zen, favor practicality over purity. Philosophically impure features that violate the canons of a computer science textbook may be the most useful to users, and vice versa. Avoid the temptation to fixate on the shiny new thing, just because it’s shiny, or because it’d be a fun technical challenge to tackle, and focus on the most practical route to putting useful features in the hands of your users as immediately as possible.
Not understanding your users’ needs - Who’s your target user? What problem are they trying to solve? How is your product uniquely positioned to solve it? It’s easy enough to look at what features you’re technically able to build, or what features your competitors implement, and match them point-for-point, without regard for why you’re actually building it. Unless your team has a shared understanding of your users’ unique needs, you’ll quickly change course from solving one problem well to not solving lots of problems at all.
Pushing complexity on to your users - Computering is hard, but that doesn’t mean your product has to be hard to use. When adding complexity to the user experience, pause to consider if there is a way — even if it requires additional effort on your part — to absorb that complexity on behalf of your users, especially if you can do it in a way that they don’t even realize you’ve intervened. If you’re in a better position to make an informed decision than your user, don’t add another setting, just make the decision. If you can correct the user’s mistake without presenting an error message, silently correct it. Heck, leverage the user’s previous interactions to hide the feature entirely if you don’t think they’ll use it. Great features are hard to build but easy to use, not the other way around.
If you see yourself mimicking one of these feature development anti-patterns, it may be time to play “feature goalie” a bit. That’s not to say you need to keep the proposed feature out of the product entirely, but it’s a good indication that you should give it a critical look and potentially scope things down to more directly support your target use case. Can you implement it without a toggle? Only expose it to power users? Bake it in to the out-of-the-box experience as a smart default? If the feature doesn’t bring your target users joy, to borrow a popular test for eliminating real-world clutter, it’s probably best to cut it. Put another way, if the feature’s not part of the solution, it’s likely part of the problem.
If you enjoyed this post, you might also enjoy:
- Towards a More Agile Government
- Ten ways to make a product great
- Why open source
- Twelve tips for growing communities around your open source project
- Securing the Status Quo
- 15 rules for communicating at GitHub
- 19 reasons why technologists don't want to work at your government agency
- Five best practices in open source: external engagement
- Four characteristics of modern collaboration tools
- Twelve things a product manager does
- Speak like a human: 12 ways tech companies can write less-corporate blog posts
Ben Balter is Chief of Staff for Security at GitHub, the world’s largest software development platform. Previously, as a Staff Technical Program manager for Enterprise and Compliance, Ben managed GitHub’s on-premises and SaaS enterprise offerings, and as the Senior Product Manager overseeing the platform’s Trust and Safety efforts, Ben shipped more than 500 features in support of community management, privacy, compliance, content moderation, product security, platform health, and open source workflows to ensure the GitHub community and platform remained safe, secure, and welcoming for all software developers. Before joining GitHub’s Product team, Ben served as GitHub’s Government Evangelist, leading the efforts to encourage more than 2,000 government organizations across 75 countries to adopt open source philosophies for code, data, and policy development. More about the author →