When you build a thing, especially a software thing, you can always make it more complicated with the hope of making it better.
Making it more complicated allows you to so try to solve more potential user problems, which hopefully anticipates the user's needs and leads to a great product.
The main question is, when is this complexity worth it?
If you don’t introduce enough complexity into your product, you can’t solve enough user problems, and it will fail.
If you introduce too much complexity, the product will be impossible for a user to understand and even more impossible for your product and engineering teams to maintain.
To me, exactly where you should fall on the simplicity—complexity spectrum is one of the harder questions to answer as a product manager.
The north star of all great product cultures is to work faster.
For every inch that you move further to the right, you hurt your ability to move faster in the future.
The complexity tax is the additional slowdown in the speed of your development driven by this complexity needing to be handled at each step of a process.
When it comes to building software products, adding additional complexity to V1 of a feature means that every step of shipping it will take longer:
This initial complexity makes getting a feature out the door more expensive, but sometimes this is worth it to take on this complexity.
However, the real cost comes with time; as you don’t stop paying the complexity tax once a feature is out the door.
This is where the real cost starts to kick in, and it can get really painful.
After your 5th meeting trying to explain how this feature actually works, you’ll start to understand the true cost of complexity.
In early 2019, the growth team at Codecademy wanted to add a user-to-user referral system for the paid product.
The high-level logic made sense; lots of other companies run very successful referral programs, which become a natural engine for growth.
In addition, Codecademy enjoys a strong brand, and lots of our free users sign up after hearing about us from a friend.
Without getting into too many details here, this was a basic user-to-user referral system.
To make sure that this was clear, we added this cute message at the top of the checkout page.
How much complexity can that really introduce?
Hint: way more than I thought it would
Cut to 8 months later, and the referral program is a very moderate success. We didn’t lose money building it, but we didn’t make that much money either. It’s a bit more than break-even.
Was it worth it to add this complexity? No, it was not, and here is why:
While this is a pretty small change, so each time we touch the checkout page, it doesn’t cost us that much; however, we touch these pages a lot.
Taking all of this into account, it was definitely not worth it. In fact, we should have killed the whole program.
There are a few takeaways from this experience (and my many others like it)
While it's really hard to determine at the start of a project when I was making this mistake, there are a few things that I should have done in retrospect.
Every time that I have made this mistake, I can point back to decisions that I should have made and didn’t.
These are always stressful; I could have chosen wrong; it makes product development take more time, etc,
However, this was always the core issue. I should have made a call on something that I delayed, and then we had to build for two scenarios that didn’t, in reality, have to happen.
One of the worse outcomes, when you introduce unnecessary complexity is that the feature kinda works, but it isn't great.
This means the thing is going to stay around, you have to maintain it, but you are not clear if you or the user get a real benefit.
This is especially true in your core product. The more often the area that you’re working on will need to get touched again, the worse this tax is going to be.
This is much harder than it sounds, as turning off features or product lines is not that simple. Inevitably there are a few users who like them; you have to manage their transition off it, migrate the data, etc.
Sometimes this takes as long, if not longer, than building it.
If all else is equal, just go with the solution that is easier to implement and maintain.
You can always iterate on it and use the information from the first launch to inform the second one.
It's natural to want your first version of a feature to work, so you think by adding more and more functionality to it, you’ll make that happen.
In reality, you could also just be delaying the lesson that you’re on the wrong path entirely.