This is the first of a few posts about my journey launching a side project in 2020.
At the beginning of 2020, I set out a goal for myself:
Build, launch, and get a paying customer for a product that I built entirely on my own.
As much as 2020 was a dumpster fire of a year, I’m thrilled to say that I managed to achieve that goal. In this post, I’ll outline why I set that goal, why I chose to build MergeCaravan, and what I learned about launching a side project.
Why Do This?
During my professional career, I’ve worked at startups in different phases and in different capacities. When I joined a catering startup called Chewse, I was fresh out of college and was joining the company as the only non-founder engineer, while the company was still pre-series A. An MVP already existed, and the company had a number of paying customers. During my time there, I learned a LOT about software development and what it takes to grow a business. As the company grew and raised more capital, I found myself doing more and more to help scale the business. Whether it was on the technical side, or when I started leading engineering, new sets of problems awaited me.
After 4 years of growth with the business, I decided to step away, and I knew there were gaps in my skills I wanted to fill. I started looking for companies that were even earlier than Chewse was when I joined and that needed makers. That’s how I found Resource.
When I joined as the 6th employee, I knew there would be a lot of new learning in front of me. However, there were several things that were the same as when I started at Chewse. Resource also already had an MVP and a set of paying customers. Yet, given the nature of the product and the size of the team, I was excited to have more influence on the Product side of things. This all brings me to why I set this goal for myself this year.
I wanted to expose myself to all aspects of Product Development and to the other aspects of launching a product. I didn’t have much experience in optimizing SEO or marketing products, so I wanted to grow in that area. I’d never found myself in a true sales role, and I wanted to learn how to do that. I’d never found myself having to figure out how to price a product, and I would have to figure that out. I wanted to be thrown into all the problems that come with launching a product yourself.
Having set this goal for myself, all I needed now was an idea for a product…
I set my initial goal without having any idea of what I would build. I just wanted to stretch beyond my engineer skillset. Knowing this in the back of my mind, I tried to pay attention to when I felt frustration during my day to day.
Eventually, I noticed something while working at Resource that kept cropping up, related to our code merging strategy. We use a slightly modified github flow, meaning we use short-lived feature branches and deploy continuously. In order to keep PR reviews manageable, we encourage small PRs and try to get them merged quickly.
We also use a monorepo, which inevitably means we have some contention for merging code, even with a small team. In order to be as careful as possible, we also require that any code to be merged has the most recent head commit merged into it. Github allows enforcing this for a branch by checking the Require branches to be up to date before merging box under a branch protection rule. By doing this, we ensure that tests are run with exactly what code will be deployed.
Our test suite takes about 10 minutes to run, so we have to wait about that long between merging each PR. When we have a lot of PRs, this means waiting with that Github PR open in a tab, refreshing until the merge button turns green. God forbid if someone else beats you to it, because then you need to merge master in and start the process all over again. Even with a small team, when you have a process that favors small PRs, and use tooling like dependabot, you can have a large number open quickly.
After thinking about this a bit, I also realized this wasn’t the first time I’d run into this problem. It was also an issue when I worked at Chewse as an engineer. Of course, when this problem gets bad enough and it takes too long to get code merged, people become incentivized to just ignore the branch protection rule and merge their code, checks be damned.
I looked at this problem, and recognized that it was a pain I could solve, so I started looking at the Github API docs to see what was available to me. The API allows fetching all the PRs that a given repo had, merging them, checking if they’re valid to merge, and even keeping them up-to-date. It looked like everything I needed was there. All I would need to do was build a service that tracked an ordered queue of PRs that were intended to be merged, keep them up-to-date as needed, and then merge them as soon as a PR was at the top of the queue.
Thus, the idea for MergeCaravan was born.
I picked a hell of a year to set this goal. On one hand, working from home full time meant that I was able to better utilize my time, so I should have had enough to commit to a side project. On the other hand, lack of clearly defined boundaries meant that sometimes I was doing the work I wanted to get done for Resource, and the next thing I knew, it was already 10pm.
Despite also having a larger amount of free time, I often found it challenging to be motivated to work on something else with everything that was going on in the world.
And to top off all of that, Resource was actually in the process of building an entirely new product. Given that I was already working at a startup which was also in the process of working on a new product launch, I knew I would have to plan my time carefully if I would have any chance of achieving my goal.
Looking back (and checking my git history) I managed to make my first commits in early May. I finished the initial prototype during one long weekend of development. All it did was listen to Github’s webhooks, and tried to merge code in response to adding a label to a PR. Simple enough. After that, I had to start asking myself what a real MVP would look like. What features were required to launch? Did I need to support different merging strategies, or could I just always use merge commits? What about reordering PRs in the queue?
I started compiling a list of what I thought was required for an MVP, and began the process of building and launching MergeCaravan.
What Did I Learn
Everyone has Daily Pain
Everyone you encounter… your coworkers, your significant other, your neighbor have things that irk them everyday. I have these too, although I think I’ve probably done a pretty good job trying to ignore them in my day to day life.
I’ll admit that I often have difficulty with recognizing these daily pains. I realize it every time I watch someone try to use a new piece of software and see what happens when something doesn’t align with their expectations. When I see these problems with the software I use, I try to imagine what the developer was doing when they wrote this, and use that as a basis for my expectations. In many ways, I think it causes me to be a bit of an apologist for software with poor usability and frankly just causes me to tolerate poor software far more frequently than I should.
I had to drop that idea and just look around me. What was really grinding my gears? One of the benefits of being a developer, is generally having a good sense about what can easily be automated. What pains were just unacceptable, and I KNEW should be automated with software? This was the area I should focus on, and not let the perspective I have as a developer work against me.
Budgeting My Time Was Key
Since I was already working a full time job at a startup that was working on a new product, I quickly realized I needed to budget my time better. One of my biggest learnings and changes this year was trying to adopt small habits that I did everyday.
Still, finding the motivation to work on a side project after spending all day working at a full time job can be really tough. Some days I wouldn’t manage to do anything but make a small copy or design tweak. Other days, I would implement entire features.
Even a habit as simple as “open the repo issues page everyday” helped to keep me moving forward. Eventually I was able to get to a place where I would work 10–15 hours per week on MergeCaravan, between a few hours on weeknights and more hours on the weekend. If I hadn’t been able to figure this out, there’s no way I ever would have managed to put enough time in.
Just Get Started
These are the words I just kept telling myself, especially as I first sat down to write code. Just get started.
I repeated them over and over to myself whenever I had the urge to read more about my chosen technology. When it comes to building, inertia is an incredibly powerful force, and it can take a lot to build it initially.
This is just a toy. Maybe I should try to find a better idea.
So what? It’s fun. Just get started.
You’re no designer. This looks like shit. Maybe I should level-up my design skills first.
Who cares? Just get started.
Will anyone even know this exists? Maybe I need to do some reading about SEO.
Fuck that. Just get started.
Over and over again, I reminded myself that none of this other stuff mattered. At least not yet. First, I needed to get started. I needed to get something out the door.
All in all, it was a lot of work, but I’m glad I “just got started”. Shipping something I built entirely on my own has been incredibly satisfying, and I learned a lot during the process.
I learned to more effectively budget my time and most importantly, I had to resist my urge to tolerate the world around me. As Paul Graham mentions:
“The advantage of taking the status quo for granted is not just that it makes life (locally) more efficient, but also that it makes life more tolerable.”
That tolerance, while comfortable, is an impediment to seeing opportunities for improvement. Once I was able to consciously cast aside that tolerance, I was able to see the possibility of MergeCaravan. While it is nowhere near complete, I’m happy with what I was able to launch.
You can find my next post about the technical choices I made when developing MergeCaravan here.