Most parts of our product are pretty easy to build. Any decent engineering team can build an events API or generate invoice PDFs (and do so quickly). It’s why so many companies build billing in-house: It looks easy on the surface.
But what makes billing hard isn’t building each system, it’s that billing is edge case hell.
Edge cases make billing hard to build
The reason billing becomes hard to build is that you need to account for edge cases you can safely ignore in other types of systems.
There are two core reasons for this:
Billing edge cases matter more
In most startups, the attitude towards edge cases is something like “Let’s fix it if someone complains.”
For resource-constrained startups, that’s often right. For an in-app survey tool, it doesn’t matter if a few users who canceled and reactivated see two in-app surveys on the same screen, which puts them in two cohorts a customer is running surveys in.
Two pop-ups are a minor annoyance. You put it in the backlog and only fix it if a customer complains. You can treat most edge cases this way.
But not in billing. Imagine you changed your billing date from each first of the month to every 30 days on the day the customer subscribed. Easy.
Now imagine the same edge case as the in-app survey. A customer (who joined before that change) churns, but reactivates their account. What if they ask for a refund? Do they get a pro-rated refund based on the day they subscribed or for the remaining days until the next month?
It’s a like the double survey: Very rare, might never happen. But in this case, it could become a compliance issue that gets you in trouble!
This is what makes billing edge cases harder: Making a mistake matters more (and you need to account for edge cases ahead of time). Charging a customer the wrong amount, messing up taxes, issuing non-compliant invoices… in billing, edge cases have serious consequences.
But hey, if that wasn’t bad enough, it gets worse :)
Edge cases scale exponentially
Edge cases aren’t linear, but exponential: The more they pile up, the harder it gets to fix them all because they overlap: You can’t fix one without touching 5 others.
Take the issue of the refund above. Imagine compounding the problem with currencies (if your customer pays you in GBP and you account in USD, how do you refund?) and entitlements (if credits that come with plans don’t correspond to dollars, how much do customers get for credits?).
And then imagine that when Peter (who left the company) built the refund system, it didn’t account for different currencies, and when Jerry built the credit system, he didn’t worry about the refunds (Peter worked on that).
So you now need to reconcile all of those edge cases, but also need to build workarounds in your own messy system because it was never built for scale.
At that point, most companies declare defeat and just throw engineers at the problem. This is how you end up with full teams of a dozen billing engineers (which is more common than you think).
The final thing compounder of problems is that you can’t hot-swap billing like you could analytics. With analytics, the worst case is no usage data for a bit. With billing, you stop making money!
And the worst part: You better know all of this ahead of time.
In billing, you need to predict edge cases
Edge cases often have to be discovered by users. A customer asks “Why is PDF data import not working for me?” and you discover it’s because your product can only read dates in DD.MM.YYYY or MM.DD.YYYY but Mongolia uses YYYY.MM.DD, so your product doesn’t work.
Annoying for a customer, but edge cases, by definition, don’t affect most users. But in billing, you can’t just charge a customer 4x what they should’ve paid and say “whoopsie, we’ll take a look”. You need to know most things ahead of time.
So you have to predict what edge cases there will be much more than you do with any other type of system.
How to get out of edge case hell
Yes, this is where I’ll say you should buy a modular system from people who’ve experienced this first hand, which happens to be exactly what the company I work for does…
But in our experience, billing isn’t something most customers should be building in-house. This sentiment is something anyone who’s built billing will agree on (read the comment on our all-time top Hacker News post if you want to confirm for yourself).
That’s because of two characteristics that make homegrown billing a bad internal tool:
You don’t drive the urgency: Building internal tools is great when you can decide when you own the roadmap instead of using 10% of the feature set of a third-party solution.
In billing, there are lots of things (e.g. regulation, pricing/monetization changes) you don’t control that require you updating the internal system, which is why internal billing teams often feel like an embedded agency than a team in a company.
Billing isn’t that unique: An A/B testing/experimentation platform is a great internal tool because you can integrate more deeply to measure specific events an off-the-shelf solution might struggle with. Billing typically falls into a few categories—all of which can be built with a product like Lago.
Is this where you innovate? Companies should focus their limited resources on what they’re uniquely good at and where they can make a difference. Billing needs to check a box. It’s something you want to get out of the way to focus on your work.
Wrapping up
Billing is edge case hell: It has more edge cases than most systems, edge cases have more severe consequences and they’re harder to fix.
It doesn’t have to be like that though: Most companies simply shouldn’t be building billing.