The hidden tax of billing and the silent burden engineers carry
API
Engineering
Billing
Payments
Mar 3, 2025
Preface
A serial founder and YC alum who’s raised over $100M across multiple startups said:
“I pay more to Stripe than I do to myself, and they can’t even tell me how much I earn in a simple way. I had to hire a full-time person who reconciles our database with theirs because Stripe doesn’t provide real-time data—let alone notify us when a payment attempt fails. Stripe cancels customer subscriptions automatically after three failed attempts. We lose the customer. We lose the revenue.”
Over the past few weeks, I’ve spoken with dozens of exceptional founder-engineers to listen to their frustrations. Stripe has done extraordinary work to liberate developers from the bureaucratic nightmare that payments used to be. They replaced PDFs with APIs. They turned a tangled mess of financial plumbing into a sleek developer experience. Startups, as a species, owe a huge debt to Stripe.
However, payments and billing are not the same problem. Billing is what happens after a payment is attempted, and is still a disaster.
There’s a moment in every engineer’s career when they realize something they assumed was simple is, in fact, unbelievably complicated. If you’ve ever implemented payments or billing, you’ve had this realization firsthand. At first, it seems straightforward. Customers pay, businesses charge, and Stripe’s API has documentation that rivals the Codex Sinaiticus - how hard can it be? Then, you start actually building it.
What you discover isn’t just complexity; it’s structural decay. Payments, despite being critical infrastructure for nearly every business, are built on layers of abstraction that were never meant to communicate with each other. It’s not a coherent system - it’s an archeological dig through financial tech spanning decades. Each layer is a relic from a different era, built with a different set of assumptions. No universal source of truth, no perfect API, no clean handoff. Who ends up untangling it? Engineers.
A founder reacting to Theo’s video on how Stripe is broken:
“My non-technical co-founder keeps asking me how payments and subscriptions can be so difficult when literally everybody does them. I just shrug.”
The Invisible Weight
Most engineering work is invisible to the outside world, but payments take this to another level. If you get it right, no one notices. The system works, invoices go out, revenue gets collected, and everything hums along. If you get it wrong - if a webhook fails, if a card is declined, if a customer is overcharged, if a usage-based plan isn’t metered correctly - it’s an emergency. It’s the engineer who takes the heat.
The worst part? The burden isn’t evenly distributed. When sales or marketing needs new pricing models, they dream it up and drop it into Slack. Engineering is where that idea collides with reality. Reality is brutal.
Consider the humble webhook. Stripe alone has 258 webhook event types. Many overlap or have subtle differences in meaning. It’s easy to map these incorrectly to significant milestones in your application. For example, when a charge attempt for a Stripe Payment Intent fails, it may not terminally mark the intent as failed, but it will mark the charge as failed. Which event should you listen for?
Similarly, on successful checkout, Stripe redirects the customer to your redirect URL with the payment intent ID. But it also sends a webhook notification. How do you make sure you don’t send two “Welcome” emails or credit their balance twice? Without protection from this complexity, even the simplest MVP needs idempotency strategies from day one to avoid duplicate billing issues.
A Redditor described their experience messing up their webhook integration:
“I was wondering why the hell our users were subscribing twice. Turns out, failed webhooks meant they weren’t being marked as subscribed at all. Stripe said ‘subscribed,’ our app said ‘not subscribed.’ Nightmare.”
Every SaaS company eventually encounters some species of the genus Payments Bug: subscriptions out of sync, invoices with missing line items, silent charge failures, mismatched revenue numbers. Engineers who work on billing don’t just write code - they become part-time forensic accountants, reconciling records between their database and their processor’s.
The Stages of Billing Pain
Roughly speaking, a startup’s billing pains come in three stages:
1. Onboarding and Integration (Pre-Seed - Seed)
One to three weeks of a founding engineer’s time setting up Stripe (justifying time spent on this pre-PMF is wild to me)
Hardcoding pricing and entitlements to “get something out quickly.”
Webhook misfires, out-of-order events, and silent failures.
Rapidly accumulating conditional logic to support pricing changes.
2. Scaling Revenue Operations (Series A - B)
Reconciling revenue across books, analytics, and Stripe.
Growing technical debt as engineering struggles to accommodate pricing requests from Sales.
First taste of international tax nightmares (hello, EU VAT).
Attempting to automate collections from delinquent accounts.
Considering third-party tools, only to find their pricing opaque and inflexible.
3. Finance-Driven (Growth Stage, Enterprise)
Building processes around procurement departments and manual invoicing.
Large-scale bank wire reconciliation.
Full-time billing infrastructure teams.
A top-contributor CTO on Reddit shared:
“We looked into third-party billing platforms, but every time, they’d break down when we needed a specific nuance. Eventually, we gave up and built it ourselves.”
Why Engineers Keep Rebuilding
For all the advances in billing, most companies still end up building custom solutions. Why?
Billing systems weren’t designed to handle real-world complexity out of the box. Every SaaS business has unique needs, and no off-the-shelf tool covers them all.
As one founder said:
“We started with Stripe Billing. Then we hit edge cases. Then we added a custom backend. Then we realized we basically built a billing system from scratch.”
The Dangerous Assumption
Many assume payments will always be this painful - that it's just the way things are. Like medieval cartographers labeling unexplored territories with hic sunt dracones - here be dragons.
My cofounder, Agree Ahmed, put it best when poking fun at this mindset:
“Why would I want to live in a safe neighborhood? I just carry a knife around everywhere I go.”
Billing pain shouldn’t be normalized. When challenged on this, many engineers started questioning whether they had toaccept this reality.
…maybe they could move to an inherently safe neighborhood after all.
A Potential Future
My heart goes out to engineers working on these problems. It’s thankless, arduous, and f**king hard work. Where do we go from here?
API-first billing – Developers need something that just works without managing Stripe webhooks. Billing should be a true source of truth.
Modular billing solutions – Instead of monolithic billing systems, companies should have plug-and-play components for different pricing models.
More pricing experimentation – Most founders we spoke to aren’t iterating on pricing as much as they’d like. Better tools could unlock this.
If you’ve ever battled payments, I’d love to hear your story. I’m currently in the midst of building something in the space so I’d love for you to treat me like your therapist and share your biggest billing nightmares with me.
You can reach out to me at harrison.telyan@flowglad.com
_
PS - If you’re one of the founder engineers who donated their time to chatting with me, thank you for your incredible generosity. You’re the ones building the infrastructure the rest of us take for granted. You’ve scaled billion-dollar startups, handled thousands of edge cases, and felt the full weight of billing’s complexity firsthand.