Valuable Life Lessons I’ve Learned as a Software Engineer

I am coming up on 10 years as a software engineer and, reflecting on the things I’ve learned, I’ve realized how many good engineering principles can be applied to living a good life.

Making Trade-offs

One thing I’ve learned early on is that no matter what decision I make when deciding how to architect a product feature, I will always need to make a trade-off. In software there are so many ways to build a feature. Certain technologies will have inherent strengths and weaknesses, and when deciding on what to choose, I have to make trade-offs in what to optimize for and what’s important for the feature. What drives these decisions when making trade-offs? Requirements. Product requirements drive how we build the feature and tell us what trade-offs to make. At work, we sometimes decide to take shortcuts in our code so we can hit a deadline faster, knowing that we will need to go back and clean up our code later. The trade-off is speed over stability. A lot of the time, we do not know if the trade-off we’ve made was the right decision until months later.

So how does this apply to life? When we make a decision, we don’t really know if it was the right one immediately. I believe all the decisions we make in life come with inherent trade-offs that we don’t always see. In our minds, we only think about the upsides and never the downsides. We want the highest-paying job, but what if we need to work 60 hours a week for it? That’s time away from our family. We want six-pack abs, but are we willing to diet and exercise for it? Our wants can be endless, but do we understand the trade-offs we need to make when it’s time to commit? Sacrifices will need to be made when deciding your requirements for life. What are your non-negotiables — your hard requirements? And will you be okay with the trade-offs? The hard part about making trade-offs are the sacrifices that need to be made along the way. My hard requirements personally are my relationships and my health. When I decided to get a dog, I knew I would need to spend more time taking care of her as well as cleaning more often, but it’s damn worth it to me, because what I gain is way more valuable.

Experimenting

Sometimes product requirements can be mostly unknown. We need to do some exploration to figure out what we’re even building. What if we only understand 20% of what we want to build? That’s when prototyping comes into play. We build something cheap and fast to validate its value and get ourselves mostly there. We don’t need to know 100% of the requirements, because sometimes getting that guarantee is almost impossible.

We can follow Jeff Bezos’s 70% rule: when you have about 70% of the information you wish you had, make the decision. When you don’t have that yet, experiment and try new things that can drive your decision-making.

It’s important to experiment in life too. I have one rule when I do: I never half-ass it. I always commit the time. When I go into an experiment without truly putting in the effort, the outcome won’t be honest. I need to make sure that (1) the experiment is actually something I want to try, and (2) it will get me to a point where I can decide if it’s worth investing more of my time and energy.

I’m in my experimental years. This year I started playing guitar — six months in now — and I recently bought a motorcycle after years of being afraid to ride. What I’ve found about experimenting is that it always challenges your assumptions. I always thought riding motorcycles was inherently dangerous, but now I know there’s a safe way to do it. These experiments help me make better trade-offs, because I’m working from experience instead of fear.

How to Measure Success?

When measuring success in software engineering, we have a couple of metrics that are important to us when deciding if a feature is successful or not. How many people use it consistently? How much money is it making the company? How many customers will be sad if they cannot use that feature anymore? These are important heuristics when understanding how impactful a feature was when it was built. This is probably the most important thing to know in the lifecycle of a feature. Is what we built successful or not? Knowing this will help make future decisions on whether to invest more time and resources into it.

How do we measure how successful we are in life? It depends on what you are optimizing for. Most people default to money because it’s the only thing with a number on it. We can always measure our self-worth by the number in our bank account, but is that a good way to measure yourself as a person? I used to think this way, but now I’ve realized it’s not what I’m optimizing for. I am optimizing for connection and health. I care about the people I love and I will always choose to spend meaningful time with them over making more money. And my health comes before it all. I can measure my health by how much I exercise each day, and measure how successful my relationships are by the shared laughs and memories I have with the people I love. When I think about my most successful relationships, I think about the deep conversations I have with those people and how their perspective impacts me as a person.

Alerting

In software, things can break and go wrong, so it’s important to have the right alerting in place. When important alerts go off at work, we drop what we’re currently doing, acknowledge them, validate that there’s a real issue, and start working on a fix. But alerting on too much is just as dangerous as alerting on too little — alert fatigue sets in and people start ignoring them. The goal is to alert on the right things so we can be proactive about solving issues before they get worse.

During COVID, when everything shut down, I stopped working out and lost a bunch of weight. I was down to 140 pounds and was fainting every time I drank. I was anemic and sick all the time. That’s when I realized I needed to start taking care of my health better.

Our bodies and minds will always tell us when things need to change in our lives — whether it’s depression or anxiety. Our unconscious will alert us when something isn’t right, and we need to listen to it and start fixing the issue or else the same alerts will go off.

Post Mortems

When shit hits the fan and it’s all hands on deck because our application is down, we all work together to diagnose and fix the issue as fast as possible. And what comes after is the post-mortem. The zero-blame structure is what makes these meetings actually work. When people are afraid of being blamed, they get defensive — they hide information, deflect, and the real root cause stays buried. Zero-blame means we’re all on the same side, trying to understand the system that failed, not the person who touched it last. That’s what allows honest reflection. My old CTO always used to say, “Never let a good crisis go to waste.”

The same is true in life, but we’re much worse at it. When we fail personally, we tend to go to one of two extremes: we either beat ourselves up relentlessly, or we deflect and blame everything around us. Neither leads anywhere useful. What actually works is the same thing that works in a post-mortem — separating yourself from the failure enough to look at it clearly. What went wrong? Why did it go wrong? What would you do differently? The goal isn’t guilt, it’s understanding. This is how we grow as individuals and gain wisdom.

Recently I had an accident where my dog fell out of my motorcycle while we were riding. I hit a bump and she fell out of the carrier — I didn’t notice until a block later. She had been strapped in, but her hind legs were scraped up badly. I felt terrible. But after the initial guilt passed, I ran my own post-mortem: the carrier wasn’t designed for a moving motorcycle, and having her loose in any container was always a risk I hadn’t thought through. So what did I learn? She needs to be strapped to my chest if we’re going on a ride. Simple fix. I’ll never make that mistake again.