This article was published on March 10, 2021

When creating a product, there’s no such thing as perfection — only tradeoffs


When creating a product, there’s no such thing as perfection — only tradeoffs

Why do we do all of the things we do, like building new products, attending planning meetings, creating new processes, or writing articles? Because someone (hopefully us!) thinks each of those things is objectively good. And if each thing is good, then collectively, they are all… perfect? Unfortunately, the math doesn’t work out that way.

There’s no such thing as perfection. There’s just a set of tradeoffs that, for a particular purpose or observer, allows you to ignore the bad and focus on the good. As you try to reach perfection by doing more things—all in an effort to avoid any tradeoffs—you eventually start causing harm. Overlapping costs outweigh benefits, and interactions between solutions start to feel weird and painful.

In other words, beauty is in the eye of the beholder… because trying to make something beautiful to everyone guarantees it will turn ugly.

This isn’t a terribly original thought, granted, but it’s something I’m thinking about a lot lately. I work in software engineering at Zapier, something I will reference a few times below, but I think the lessons here are universal.

How the pursuit of perfection can create a monster

It all starts innocently enough. We’re doing some good things.

A circle with three circles inside it. The big circle is labeled "All the stuff we 'should' do"; the three small circles are all labeled "All the stuff we're doing."

But we realize there are all these other things we should be doing too, so we try to do all the things. Eventually, we create a monster.

The same circle as above, but this time with 13 circles inside, some labeled "Waste of time," and some labeled "Stuff we shouldn't be doing, but for some reason have to" and "Weird stuff that makes no sense." One circle outside the others labeled "WTF?"

We end up in a trap we can’t get out of.

Every meeting is good, so all have to be attended. Every process is good, so all have to be followed. Every tool is good, so we have to use all of them. All features are good, so none can be removed from our products.

These tendencies mean, in aggregate, that we can end up with very little time to actually build anything. Our products can become more complicated, and there’s no time to simplify things.

The result? Thin slices of productivity get further subdivided by the complexity tax. The fun parts of the product get obscured by the clunky parts.

[Read: How do you build a pet-friendly gadget? We asked experts and animal owners]

I don’t have a perfect answer for situations like this. It’s easy for someone on the team to say you should do less, but it’s much harder for a team to agree on what you should stop doing. The “correct” subset, after all, is subjective.

And even if you could agree, it takes time to simplify things. It’s ironic, but it usually takes time to stop doing something. In software engineering, for example, removing a feature takes time because you have to remove the code, update your docs, and more.

Having said that, there are some things you can try.

Try to be complexity neutral or better 

If you’re asking someone to do something, think about how you can make their lives easier and not just harder. That means asking potentially counterintuitive questions.

Is there an existing process you can remove to make room for a new process? Is there some other task you can at least delay to give time to build a new habit? If you’re asking someone to use a new tool, can you give time for training? If you’re already adding some other new tool, can you just finish that transition first? When you hire someone, can you think about what they might remove and not just what they will add?

These aren’t obvious questions, but they’re necessary. Make sure you’re asking them.

Acknowledge the math

It’s not possible to do everything. The more you try to do everything, the more you’ll take shortcuts. You’ll just check a box, and as a result, you’ll create those weird overlapping circles I showed you above. Or you’ll start doing things that you arguably shouldn’t even do.

Some tasks require waiting on other people to complete their tasks. This is called wait time. There’s basic math at play here, which this chart shows well.

A graph with x-aces "% Resource Busy" and y-axis "Wait Time" showing a very gradual incline as % Resource Busy increases, until it hits 90% Resource Busy, at which point it shoots up toward infinity.

If you don’t trust the math, there’s a great video that illustrates this “resource utilization trap.”

If you don’t have idle time, wait times effectively reach infinity. If you feel like nothing is getting done but you’re really busy, it’s probably because everyone is busy waiting on each other. There are two solutions to this:

  1. Have more idle time

  2. Remove the need to wait

Both are important. You can never remove all dependencies, so you have to have some idle time to help each other. But you do want to remove as many dependencies as possible, so that people can help themselves.

At Zapier, this reality motivated some key changes: we’re working on making different parts of our product less interdependent. This means each team that owns a service can make autonomous decisions, so they don’t have to wait on other teams.

But when you remove dependencies in this way, you really have to remove them. If you do the work of dividing up parts of your product but teams still consult each other on every decision, then you’ve actually just made the problem worse. You’re paying for more people to do the same job, but slower.

Sometimes you’ll have no choice. There will always be things that require teams to cooperate. In other cases, the cost of inconsistency is too high. This is why you need to reserve idle time for these cases.

Make explicit tradeoffs 

If you accept that perfection can’t be reached, and that everything you add has the risk of making things worse, then you can start making tradeoffs.

It’s easy, if you have a problem, to think of the solution in isolation—to work as though you have infinite time and energy for that one solution. But you exist in the physical world, where there are constraints.

The desire for consistency has tradeoffs. Teams can either be free to ship what they want and how they want, or they can be forced to use a shared solution and follow a shared process. Sometimes you have to choose the latter, but you have to be aware of the impact that has. Ignoring that means accepting an ad hoc mixture of chaos and deadlock.

Our product at Zapier is a good example here. Our desire to have a single product that fits every use case and every customer has tradeoffs. The product is a blank canvas, which can make the value proposition hard to grok. We’re continually balancing ease of use and power.

One option for us might be to create specialized products that are easier to understand. The problem, of course, is that this would mean more complexity in our documentation, support tools, onboarding, organization—the list goes on. Those products also might not always integrate well, and customers might get confused.

That tradeoff is fine, as long as we’re explicit about it and everyone understands it. If we want to avoid that confusion, we’d have to invest more in a consistent experience for our users, which is another tradeoff since that’s time we can’t be using to build more products.

I could go on. The desire for planning and visibility and metrics has tradeoffs too. We do these things to make better decisions—that is, to make perfect tradeoffs. But there are no perfect decisions. Sometimes we just need to acknowledge the math, promise to be complexity neutral, and plan for a potential rollback if things turn out ugly.

This article by Justin Deal was originally published on the Zapier blog and is republished here with permission. You can read the original article here.

Get the TNW newsletter

Get the most important tech news in your inbox each week.

Also tagged with