For what feels like forever now, there’s been an ongoing debate about the rising complexity of web development. Developers feel overwhelmed with the amount of choice they face when starting a new project. Which framework – or now, metaframework – should you choose? Which testing library? Which build tool? Which cloud provider?

There’s a real belief, I think, that these choices will be a crucial factor in determining the success or failure of your work – and maybe even your career. After all, no one wants to adopt a framework or practice, then find out in a few years’ time that that choice has fallen out of favor. As an entrepeneur, that could mean facing challenges that you can no longer find great developers to work on your tech stack, or be mired in a years-long rewrite when you could be shipping product. As an individual contributor, it could mean fears that your skills won’t be marketable in a few years time.

If those feelings sound familiar to you, I want to share a story that I hope will offer some comfort. It’s about a time early in my career – way back in 2007 – when I joined FreshBooks, a then-nascent SaaS business, as employee #7.

Joining the cool kids

If you’re not familar with FreshBooks, it’s a popular SaaS product that helps freelancers and entrepreneurs send invoices to clients and collect payment online. You sign up, punch in some information about the work performed and how much it cost, then FreshBooks sends an email to your client inviting them to a page where they can review the invoice and submit payment online. On top of this it has a host of other features, like time tracking and even full-blown double-entry accounting.

FreshBooks Logos past and present
The original FreshBooks logo (left) was pretty cool back in 2007. It stuck around until 2020, when it was replaced with the logo on the right.

Back in 2007, FreshBooks was a much smaller company operating out of the basement of one of the founder’s parents’ basement (Mike McDerment). There were far fewer customers, and the product looked a lot more rough, but the key value proposition – send your invoices online and get paid faster – was there. You could even send paper invoices via snail mail back then, which was a unique offering that helped the business stand out.

FreshBooks didn't just serve freelancers. Later in my career, I worked for a handful of startups in San Francisco that used FreshBooks to invoice some of their earliest enterprise deals.

Despite being a small company, FreshBooks was a local darling of the web 2.0 era. They were part of a wave of innovative companies that were taking what were traditionally desktop software products and putting them on the web, at a time when browser technology advances like AJAX were making decent web-based experiences possible. FreshBooks was thus often mentioned in the same breath as other companies building web-based SaaS products, like 37signals’ Basecamp, which is how they got on my radar.

When I saw the job posting come up for a Software Developer to join their team, I’d already been following them for a while, knew they operated in the city, and was really, really hoping to get the job.

At the time I was a year removed from graduating university, and was working at a tiny web consultancy that contracted exclusively for Four Seasons (not the landscaping company). We oversaw Four Seasons’ gift card fulfillment and guest profile web presence, which was all written in a custom scripting language executed through cgi-bin. In my evenings, I messed around with Ruby on Rails, and maintained a Rails app that managed my floor hockey league’s player and team stats.

If you’ve ever been a part of the Ruby and/or RoR communities, you’ll know they’ve always placed a lot of emphasis on beautiful code. And at the time I was hitting that sauce hard. I would spend a tremendous amount of time reading “how best” to do things: how to write code to be as DRY as possible, how no function should be more than a few lines of code, how my code should read left-to-right, etc. I was one of those people.

FreshBooks was written in PHP, which – besides maintaining a phpBB forum for a brief period – I had no real experience working with. But despite the skills gap I was called up for an interview, met the whole team, and found out a few days later I’d got the job. I couldn’t tell you how psyched I was to join a legit web 2.0 business with actual paying customers. How bad could PHP be?

A harsh reality

When I finally started the job and got access to the FreshBooks codebase, my heart sank. I’d come into this job thinking I was joining an outfit that had figured things out, but their PHP codebase looked nothing like the RoR projects I’d built. The code did not use a framework of any kind, had a ton of copy/pasted code, and code reuse was achieved – not by calling functions – but by importing entire PHP files that depended on a tangle of global variables.

The first FreshBooks office in Mike's parents' basement
Me (left) and fellow basement-dweller Daniel Tsang (right) in the first FreshBooks basement office.

The developer experience also felt several steps behind. Unlike RoR, where I’d become accustomed to editing and running code locally, the FreshBooks PHP application only ran on a single shared Linux development server (but to their credit, it was a 1:1 replica of the production server). To make changes to the codebase, we used Dreamweaver to basically live-edit files on the server over SFTP. You had to be careful not to edit the same file as a colleague or you risked overwriting their work. You literally had to yell out, “Hey everyone, I’m editing invoice.php now” to make sure you had the file to yourself (we all worked in the same room). And you’ve probably figured out by now that there was no source control either.

I don’t remember a lot of my initial work on the FreshBooks codebase, but after a few months, I had done enough to engender the respect of my teammates and started leading some refactoring initiatives and development experience improvements. I stood up a Subversion server on our new internal development box – a cheap desktop PC named “Optimus” we kept in the closet (classic) – and trained everyone on TortoiseSVN. I set up everyone’s Windows machines with VMs that ran roughly the same LAMP stack as our production environments, so that we could edit and run code locally. And I introduced unit tests and automated testing, which I used to start slowly refactoring the code away from file includes and global variables.

Screenshot of the FreshBooks Invoice page circa 2008
I helped ship this version of FreshBooks' Invoice page in 2008. It was one of my first real-world JS optimization challenges; there was no cap on the number of rows you could input, and some users had thousands of rows that would cause the browser to hang.

I want to emphasize that none of this was easy. Not just the technical challenge, but the challenge of getting people onboard with these ideas after they’d been used to working one way for so long. But the progress was happening, and things were looking up.

Defending an inherited codebase

Somewhere in the middle of all of this, I was given a new and unexpected task. We were about to close a large-ish angel investment (large to us at the time, that is), but the investor wanted to perform some due diligence on our codebase beforehand. They would be bringing in a trusted colleague, a distinguished engineer from a large-ish technology company, to review our code and help assess our technical acumen.

Even though I was still relatively new and hadn’t authored much of the code, I think I was starting to be acknowledged as the codebase’s new steward, and was asked by the company’s leaders to sit down and guide the reviewer through it.

This was a stressful proposition. The impression I had at the time was that this investment was contingent on us passing this technical diligence phase. And I was being asked to guide the reviewer/assessor through our source code. What would happen if I failed?

When the day come, we had a PC set up in a meeting room with 2 seats – one for me, one for the reviewer. He was a tall, imposing man, probably in his late 30s or early 40s, and putting out “wise Unix greybeard” vibes. He opened up the file editor, and started opening source code files and scrolling through the code. I sat to his side, nervously fidgeting, while a handful of employees stood anxiously behind us.

AI portrait of the pairing scene generated with Midjourney v6
There is no picture of this event, but to help you visualize it, I generated this scene with Midjourney v6. The guy on the left definitely looked like me back then, minus the wardrobe choice.

Every time he stopped at a file to take a closer look, revealing the mess of global variables and questionable coding practices, I clumsily tried to explain why things were the way they were while apologizing for the sorry state of affairs. Even though I’d only written a little of it, I felt personally embarrassed, and was certain we were toast.

After 10-20 minutes of this, the reviewer eventually paused and said:

“Yep, it’s bad. But I get it. This is how everyone used to write PHP. You’ll make it better over time. Looks like you’ve already started. The thing is you solved the hardest problem: you built something that people are willing to pay for.”

The whole session lasted maybe 2 hours tops. My brief role was finished; I returned to my desk while he met privately with the leaders of the company. It was the first and last time we’d met.

The hardest problem isn’t code

FreshBooks secured the investment. And the reviewer was right: over time the business kept growing, and we kept improving the codebase, the tooling, and the developer experience along the way. I left FreshBooks in 2010, but other teammates continued that journey for years to come. By the early 2010s, the entire backend was re-written in Python, and in 2016 they launched a from-the-ground-up rewrite of the product in Ember.js.

Today FreshBooks employs over 500 people and was last valued at $1 billion.

This experience taught me a valuable lesson about software development. For all the emphasis our industry places on getting things “right” – using the right tools, the right practices, etc. – at the end of the day, we’re writing code to serve some kind of product goal, and making that product successful is the real problem you’re trying to solve.

And for folks who’re worried that working on a messy codebase or unpopular tech stack might hold them back career-wise, YMMV, but I didn’t feel that was true for me. On the contrary, it ended up being an opportunity to develop valuable skills I would have never learned had those early messy problems already been solved. And when I began hunting for my next job in San Francisco in 2010, most shops wanted to interview me on the strength of FreshBooks’ success in the marketplace – not its code. Sure, I still had to pass the technical screens, but I believe what mattered most to employers about my resume – the thing that got me in the door – was that I’d been a part of a company that had solved the hardest problem.

I want to thank Mike McDerment, Joe Sawada, Levi Cooperman, and the rest of the FreshBooks basement crew (Jeff, Daniel, and Kathy) for taking a chance on me. And to Rich Lafferty and Jaco Joubert, other early FreshBooks-ers, for reviewing this post and assuring me my memory isn't completely shot yet.