Image by Free-Photos from Pixabay

Dear New Engineer,

We’re thrilled to have you join our team! You asked insightful questions during the interview, and your technical skills are top-notch. Furthermore, you set up your local development environment in record time. Well done!

Looking through the code base, you identified numerous issues and places that need a lot of refactoring. And everyone on the team agrees that our codebase has some really dark corners.

But before you go on a quest to re-engineer our entire system, I want you to consider five things:

1. We’re in growth mode.

We’re a start-up. We have a few customers, and our biggest risk is not shipping features fast enough to get more customers. If we don’t grow enough in the next 18 months, we won’t qualify for Series A funding. As a result, we have a tolerance for non-severe issues.

So please, stop comparing us to Facebook and their supposed best practices because a tiny bug for them could affect millions of users.

2. We only have 15 customers and 200 active users right now. So it doesn’t make sense to scale things past 150 customers and 2,000 active users.

Too often, we believe future problems—which are largely imaginary—must be fixed now. If we can imagine a dozen issues, they must be real and must be addressed today.

For example, scaling our billing system to handle 100,000 customers is something we can conceive of. (And it’s a fun problem to solve!) But it won’t happen any time soon, or this year, or next year, and therefore doesn’t deserve our immediate attention. Instead, it would be a massive distraction from issues that customers face right now and features that customers want right now.

3. We need firm limits on future-proofing things that could go wrong, so there’s enough time to handle the things that do go wrong.

We believe that we can predict all problems that’ll pop up and create chaos in our systems. But we can’t. Numerous issues will surprise us as we add users and queues and features and automated billing and multiple regions and internationalization and timezone support. Stuff is going to blow up! In our retrospectives, we’ll say, “I should’ve seen that coming.”

But we seldom anticipate these things because software is incredibly complex. Our little brains didn’t evolve to manage this much complexity. Consequently, let’s not pretend like we can anticipate everything that will happen. Instead, let’s prepare for the obvious stuff and give ourselves some extra time to handle the surprises that will inevitably happen.

4. Consider all the things that you’re saying “No” to.

Every time we say “Yes” to something, we say “No” to a dozen other things. Other issues. Other features. Other parts of our system screaming to be refactored. There’s just not time to do it all.

In fact, there are 4X times as much work as there is time to do it. So we make tough decisions about the 25% of tasks we work on and the 75% that we put on the back burner. And eventually… forget about.

It hurts my heart to say this, but our “backlog” is largely a list of work we’ll never get to. As such, we must be careful about what we say “Yes” to!

5. Consider all the things that you’re saying “Yes” to.

Before embarking on a refactoring project, map out what completion materially looks like. Think through all dependencies, sub dependencies, and so forth. Walk through the edge cases for each dependency. Is this project still worth doing?

Next, given an honest time estimate for each dependency, sub dependency, and edge case. Is this project still worth pursuing in light of everything else that you might work on?

Thanks to Todd Ericksen and Thomas Weigel for a reading draft of this.