What I Learned - 2019

Lessons and learnings from 2019.

At the end of the year I like to write up a collection of interesting things I've learned from the past year. I've seperated it out across three areas—professional (things I've learned at work), personal (things I've learned that are more personal), and tech (thoughts cultivated from side projects and other exploration). Happy New Year!


Engineering for growth part II

Last year I started down the journey of engineering for growth and this year I learned even more the hard way. Here's a couple of key takeaways that seemed to have helped the team:

  • Spend more time defining the problem: It's easy to jump straight to solution mode without really thinking through the problem. The better defined the problem, the more obvious the solution and it's relative priority. To do that, we spent more time defining the indisputable facts (usually some queries and data) and then interpreting what we're seeing before thinking of the optimial way to address it.
  • Product problems vs growth problems: Some engineers are put off by "growth work" for some reason. I think it tends to conjure up a 'emotionless mega corp growth for nameless customer' kind of feeling. However, I've found that most growth problems we worked on were actually product problems i.e. product is too hard to use, understand, or access. In fact, the biggest 'growth hacks' came from deeply understanding the user journey and product which had nothing to do with button color or CTA.
  • Drive change with metrics: Making metrics a key part of our workflow made it clear what was working and what wasn't. We insisted on making observable improvements that should have a noticeable impact. Not everything needed to be A/B tested, but being able to measure the key metrics that drove change was important to building a feedback loop to inform future changes. Even better, focusing on metrics led to more questions about the fundamental mechanics of what drives our business.


I learned about SCQA (situation, complication, question, answer) from a co-worker (thanks Jeff Weinstein). It's a simple framework to organize your thoughts in writing and think more clearly. I've found this has been one of the most positive changes I've made to my professional writing. The main insight for me was decoupling the context from the problem (situation and complication repectively, in Minto's terms). This makes it clear what the facts are and how you are framing the problem. I've applied this to just about all product documents and roadmap decisions with excellent results.

Avoid monolithic ships

Earlier this year we needed to make a tough call and cancel a project. The project fell victim to trying to do too many things at the same time—address technical debt, improve the product, and reduce operational overhead. We knew it was risky going in, but we didn't pay enough attention to was how long it was going to take relative to the value.

To steal a concept from finance, I learned that the payback period of engineering work needs to be in line with the value being delivered. As time approaches infinity, the value of an engineering project approaches zero. Time is a significant factor and if you don't have a good idea of when it will pay off, you don't understand the work well enough.

We asked, is this the best place to invest our time right now? At what point would we provide value to our users? Is it all or nothing? This led to tough conversations, but ultimately we made the adjustment we needed and found a new approach that started to pay back much sooner.

It takes time to ramp engineers

As an industry, I think we underestimate how much time it takes to ramp engineers on a new team and domain (yes even senior engineers). From my observations in building out the team this year, we underestimate how much context is needed to be productive and how important it is to gel as a team. We need a better understanding of the factors to ramping up on technical teams so we can build better processes.

Remote engineering is taking off

After spending significant time this year recruiting (hosting a 1,000+ person remote coffee chat!), hiring, and managing remote engineers I'm excited for the future of distributed work.

In managing a remote team, I learned the importance of setting good norms and doubling down on async team processes (e.g. conference room-less meetings, memos, design docs, briefs, meeting notes).

After speaking with over a hundred remote engineers this year, I learned that the demand for working at a tech company that 'really gets it' with respect to remote teams is quite high. I'm surprised how poorly the industry has supported distributed teams thus far given all of the well-covered upside for worker happiness and recruiting.

Maybe you don't need another platform team

Not every internal engineering team should become a platform team. If every team is a platform team and everything is self-serve, more work and complexity will end up being propogated to the highest layer of the stack—usually a product team. Teams becoming a platform take time to mature so you end up regularly churning code and abstractions that others rely on. This kills productivity for the teams that often need to be able to move the fastest.

So what's the answer? I'm not totally sure, but it should obtimize for stability of well defined boundaries and minimize the amount of context required to self-serve. If it's not well defined, is it even a viable platform or is it a headcount problem?

Layers have weight

I saw Jonathan Blow speak at a conference and one of the takeaways from the talk was a reframing of a mental model many of us in software engineering seem to have—you can keep adding layers of abstraction for free. We've all suffered from this line of thinking in some way e.g. a leaky abstraction, but I found the mental image of 'layers have weight' to be very useful at intuiting the problem.

Jonathan argues that we should think more like architects of physical buildings when writing software. You can't build an infinitly tall house because each additional layer has weight and you should be thoughtful of what building materials are used. When writing software, be mindful of each additional layer of abstraction and consider that it might introduce more weight than the structure of your program (or team) can handle leading to unnecessary toil and low productivity. It feels like an important insight that I'm still chewing on.


Typed languages are wonderful

I feel confident that typed languages (and gradually typing dynamic languages) are slowly eating the industry (again). At work we've been using Sorbet (Ruby type checker) extensively which brings the good parts of static typing (e.g. real enums, exhaustive type checking) to an otherwise magical (in a bad way) dynamic language.

This makes a lot of sense for large engineering organizations that coordinate across many boundaries. It opens up the ability to invest in new tools (e.g. VSCode integration, better jump to definition, refactoring, etc.) which can significantly improve the leverage of a large group of engineers.

Even in the small, I've learned to embrace type checking as a way to get fast feedback when writing Rust (i.e. write some code, jump to next compiler error, repeat). Coming back to code later and reasoning about the flow of data is easier.

Game engines and Rust

I find writing games to be fascinating and spend maybe too much time thinking about game engines (or writing game engines). This year I explored writing games with Rust.

I started with Amethyst, but found I was spending too much time doing busywork (e.g. tile maps, sprites, animation, map coordinates etc.) and not enough time working on my intended goal—a simulation. I learned that even though I enjoy playing with nascent tools in new programming languages, it's just not very productive. For simple games (2D sprite-based) you may as well roll your own engine in Rust.

However, I did find an interesting new angle to explore—using "real" game engines to offload the busywork of collision detection, path finding, ray casting, etc and using Rust to write the brains of the simulation. I use Godot's native bindings for Rust which, so far, works surprisingly well! Godot has it's own quirks, but it's a well supported project that makes it easy to get something up and running. (I should note, I've played with Unity too, but it doesn't have nearly as good support for interoperating with other native languages like Godot does).

WebAssembly and distribution of applications

I was interested in exploring the intersection of WebAssembly and mobile apps so I built Woz—a progressive WebAssembly application framework. I started thinking more about content and distribution of the web and how, with a few different choices, we could end up with an application ecosystem that is easier to distribute (browsers), build (unified target i.e WebAssembly), and distribute (hyperlink vs app store).

I'll be keeping an eye on how WebAssembly progresses—the promise of a performant runtime and ubiquity of the web is compelling. You can hear more about my views on this topic from the talk I gave at WebAssembly SF.


Read more, watch less

My commute changed again this year and it involves more waiting and sitting on a bus. This affords some extra time for reading. In the morning I prefer to read non-fiction books where I can learn something new. I normally struggle to stay motivated reading non-fiction, but doing so in the morning—when I have the highest willpower—works well. This also carried over to entertainment, my wife and I now read instead of watching TV (usually).

Spending more time reading has increased my reading speed significantly, but also increased my enjoyment—finding the right book/author is as delightful as {insert favorite HBO show here}. It's worth trying to find the kind of books that make you excited to keep reading.

ISOs, NSOs, RSUs, and taxes

I can better appreciate all of the work that goes into financial planning for people with significant stock options of various types. It's fascinating how complicated it is and, although a bit agonizing, I enjoyed learning more about the differences between ISOs, NSOs, RSUs, and their tax treatment over time.

It can be difficult to optimize on your own and there is significant downside to not planning. There's room for better tools to help plan for an individuals unique situation and I'm surprised how little information is published for fear of giving bad advice (I rewrote this section several times worrying about misleading anyone!).

Facts and Opinions

One of the most interesting things I learned had to do with journalism—specifically fact-based vs opinion-based. More people are consuming news that is opinion-based. This is more troubling because of the difficulty of distinguishing facts from opinions. I keep reminding myself to put in the effort to distinguish facts from opinions especially when it doesn't support my closely held beliefs.

Intermittent fasting for more productive mornings

Yes, I too skip breakfast. What started as an experiment is now a consistent part of my day. My mornings have been noticeably more productive, presumably because I don't have post meal sluggishness sapping my focus. I now prefer to do heads down work in the morning—something I never would have thought would be true for me! I have yet to read anything comprehensive about mental performance and intermittent fasting, but it does seem to benefit me (at least in the morning).

Wrapping up 2019

It's been a year of exploring new things and hard-earned lessons. I've grown as a leader and manager, worked on hard product problems, and solved interesting technical challenges. It was fun to get back to giving technical talks and I enjoyed meeting a ton engineers through remote coffee chats. I'm looking forward to 2020!