5
17 Comments

I found $2,300 leaking silently from a founder's Stripe account. He had no idea for 11 months.

One founder had been leaking $2,300 per month for 11 months.

His dashboard looked completely normal the whole time.

Here is what was happening:

Every time a payment failed, Stripe sent invoice.payment_failed to his webhook.

Server returned 200 OK. Stripe considered it handled and stopped retrying.

But inside the handler, nothing happened.

No access revoked. No database updated. User kept full access.

For 11 months.

I recently reviewed 6 Stripe setups manually using just a restricted read-only Stripe key. No code access needed.

The numbers across all 6:

• 4 out of 6 had at least one critical webhook gap
• Average monthly leak — $340
• Largest single finding — $2,300 per month
• Most common issue — invoice.payment_failed acknowledged but never acted on

Eleven months. Average $340 per month. These founders had no idea.

Here is how to check yours right now in 5 minutes:

Stripe Dashboard → Developers → Webhooks → Your Endpoint → Recent Deliveries → Filter by 'invoice.payment_failed'

Look at what your server returned.

Then open your webhook handler and find that event case.

Is there actual logic inside database update, access revocation?

Or is it logging and returning 200?

If the second one, you may already have this gap without realizing it.

I put together a 7-event audit checklist covering every critical Stripe event that needs proper handling, the exact same checklist I use for manual audits.

Comment "checklist" below or mail me at [email protected].

Free. No pitch.

If after seeing the checklist you want me to run the full audit on your account:

That is also free.

posted to Icon for group Building in Public
Building in Public
on April 18, 2026
  1. 1

    Growth dashboards hide leaks because normal just means on-trend. The bugs that survive 11 months are the ones that never cross a threshold alert. $2,300/mo on a founder doing $50k MRR is 4.6 percent. Inside noise band. Every anomaly detector tuned for growth misses the drift. What did the anomaly finally trip on?

    1. 1

      It never tripped on an anomaly detector, that is the whole problem. The leak was only visible when I manually cross-referenced invoice.payment_failed events against downstream subscription state changes. No threshold was crossed because MRR was still growing from new customers masking the loss. The drift was invisible to any growth-oriented metric. What caught it was looking at the intersection of two specific data points simultaneously, who failed to pay in Stripe and who still had active access in the database. Neither system surfaces that intersection automatically. You have to deliberately query for it. That is exactly why it survives 11 months inside the noise band.

      1. 1

        That intersection query is the bug class nobody writes about. Stripe owns money state, your DB owns access state, and they drift by default. Every serious B2B ships a nightly reconciliation job that cross-checks who paid against who has access. Most teams skip it until one customer costs them $25k.

        1. 1

          Exactly right and that reconciliation job is the single biggest gap between a production billing system and an MVP billing system. What I keep finding is that AI tools generate the webhook handler and stop there. No reconciliation job. No state machine. No fallback. Just a handler that assumes perfect delivery every time. The founders who built with Cursor or Lovable have the webhook. They do not have the reconciliation layer. That is why the drift compounds invisibly. The handler looks complete. The system is not.

  2. 1

    This is one of those things people don’t notice until it’s too late.

    Small leaks don’t feel urgent, but over time they add up more than obvious mistakes.

    Makes me think how many “invisible inefficiencies” exist in other parts of workflows too.

    1. 1

      Exactly this. The dangerous ones are never the obvious failures, those get fixed immediately. It is the silent ones that compound quietly for months while everything looks fine on the surface.

  3. 1

    This is actually scary — especially because everything looks normal on the dashboard.

    Most founders assume 200 = handled, but that’s just delivery success, not business logic.

    Curious — in your audits, do founders usually miss just this event, or are there multiple silent gaps across other Stripe events too?

    1. 1

      In almost every audit it is multiple gaps not just one. The most common pattern is invoice.payment_failed and customer.subscription.deleted both mishandled simultaneously. One lets failed users keep access. The other lets cancelled users keep access. Together they stack. The scary part is each one individually looks small but they compound on the same user base month after month. Have you checked yours recently?

      1. 1

        That compounding effect is what makes it dangerous — each gap looks small in isolation.

        I’m curious — when you audit these, is the root issue usually missing logic, or more about founders assuming Stripe handles more than it actually does?

        1. 1

          Both, but the assumption problem is deeper than the missing logic problem. Missing logic can be fixed in an afternoon. Wrong mental model about what Stripe actually does versus what founders think it does, that takes longer to correct. The most common assumption I see is that Stripe manages access. It does not. Stripe manages payments. What your app does with payment events is entirely your responsibility. Founders who built with AI tools inherited code that looks complete because Stripe's side is handled perfectly. The gap is always on the application side, the 15 lines of logic that should live inside each event handler that never got written. The AI generated the switch statement and the cases. It just left the cases empty or with a log statement.

          1. 1

            Yeah — and this is exactly where most founders underestimate the problem.

            They think it’s a “bug”
            but it’s actually a revenue leak system

            Because once that mental model is wrong, it’s not just:
            invoice.payment_failed

            it’s:
            → retries not handled properly
            → access not revoked correctly
            → edge cases stacking silently

            And the worst part:
            you don’t notice it until months later, because nothing “breaks”

            At that point it’s not a fix, it’s recovery.

            That’s why tools here don’t win by “monitoring Stripe”
            they win by:
            → catching leakage early
            → and showing “you’re losing $X right now” clearly

            Otherwise it stays invisible.

            If you had to simplify it:
            is this more like a recovery system or a leak detection system?

            Because those land very differently to a founder.

            1. 1

              Detection first, always. Recovery without detection is just dunning, and there are already tools for that. What makes the leak invisible is not that nobody wants to fix it. It is that nobody knows it exists. The founder does not know invoice.payment_failed fired 23 times and nothing happened downstream. They have no dashboard for that intersection. Detection surfaces the number, you are losing $340 per month right now, here is the event ID, go verify it yourself. Once the number is visible the urgency to fix it is automatic. A founder who sees $340 per month leaking for 11 months does not need convincing to act. They need the proof they never had. That is the detection moment. Everything after that — fix instructions, implementation review, done for you. is just the natural next step once the proof exists.

              1. 1

                That’s exactly the wedge.
                Once the number is visible, the product sells itself.
                Which also means the real leverage isn’t just detection — it’s how fast and clearly you surface that “you’re losing $X right now” moment.
                If that lands instantly, everything after becomes a formality.
                Curious — how are you thinking about making that moment hit as fast as possible for a new user?
                Also, are you on LinkedIn? Would be good to continue this there — I’m Aryan Y.

  4. 1

    Great insight, very concrete and actionable.

    But here’s the nuance: the issue isn’t just the webhook, it’s the lack of clear state management. If everything depends on events, any failure breaks the system.

    To make it more robust:

    Add periodic checks (cron) against Stripe as backup
    Define explicit states (active, past_due, canceled)
    Trigger alerts when failed payments aren’t handled

    Webhooks should be a trigger, not your only source of truth

    1. 1

      This is exactly right and an important distinction. Webhooks as the only source of truth is fragile by design, any delivery failure or processing error creates drift between Stripe state and app state silently. The cron reconciliation layer is what separates a production-grade billing system from an MVP billing system. Most AI-generated codebases have neither the state machine nor the reconciliation job, just the webhook handler, and often an incomplete one. What stack are you running? Curious whether you built the reconciliation layer yourself or used a library.

  5. 1

    “This is such a silent killer — everything looks ‘working’ while revenue quietly leaks.

    The dangerous part is exactly what you said: 200 OK gives a false sense of safety.

    You should test this in a live setting as well — we’re running a small round where builders bring ideas like this. $19 entry, winner gets a Tokyo trip (flights + hotel).

    Round 01 just opened (100 cap) — best odds right now.”

Trending on Indie Hackers
I launched on Product Hunt today with 0 followers, 0 network, and 0 users. Here's what I learned in 12 hours. User Avatar 128 comments The most underrated distribution channel in SaaS is hiding in your browser toolbar User Avatar 110 comments I gave 7 AI agents $100 each to build a startup. Here's what happened on Day 1. User Avatar 73 comments A simple LinkedIn prospecting trick that improved our lead quality User Avatar 60 comments Show IH: RetryFix - Automatically recover failed Stripe payments and earn 10% on everything we win back User Avatar 32 comments How we got our first US sale in 2 hours by finding "Trust Leaks" (Free Audits) 🌶️ User Avatar 23 comments