---
title: "Epic Devs (@epicdevs) | Hashnode"
description: "Building dual-platform SaaS on nights and weekends. No fluff, just code, Stripe nightmares, and the reality of shipping"
url: "https://hashnode.com/@epicdevs"
---

@epicdevs

# Epic Devs

@epicdevs · London, UK · Joined October 2026

Building dual-platform SaaS on nights and weekends. No fluff, just code, Stripe nightmares, and the reality of shipping

## Comments

[So true — billing cycle two is the real launch. Test mode teaches you how subscriptions start; production teaches you how they fail. The past\_due vs canceled distinction bit me too. At first I was revoking access on the very first invoice.payment\_failed, which nuked users whose bank would've approved Stripe's retry two days later. Now I keep entitlements alive through the retry window (Smart Retries + dunning emails enabled) and only flip to canceled when Stripe says the subscription is genuinely dead. And the card-update half is why I eventually added a "payment failed — update your card" screen that deep-links to the billing portal. Tiny feature, outsized churn saver. Did you bake a grace period into your own entitlement logic, or do you let the payment provider's retry schedule handle it entirely?](https://hashnode.com/posts/why-stripe-test-mode-lies-a-solo-dev-s-36-hour-payment-infrastructure-trench-warfare/6accab3a2cf2ed754311386a/comment/6ad89c7aa7508b2879f9f9bb#reply-6ad8a9ff10e63767dd0e8890)

Reply · Article · Oct 21 · [Why Stripe Test Mode Lies: A Solo Dev's 36-Hour Payment Infrastructure Trench Warfare](https://hashnode.com/posts/why-stripe-test-mode-lies-a-solo-dev-s-36-hour-payment-infrastructure-trench-warfare/6accab3a2cf2ed754311386a)

[Thank you! And honestly — re-fetch alone WAS enough for state correctness, and that's the part I'd emphasize to anyone pre-payments: if every handler re-fetches live state by subscription ID instead of trusting the payload, processing becomes convergent. A duplicate event just re-fetches the same truth and writes the same row. Duplicates become harmless no-ops against the DB. Where it still bites is side effects. The DB converges, but nothing stops a duplicate from re-sending the "Welcome to Pro" email, double-logging an upgrade analytics event, or burning a redundant Stripe API call. So no — I didn't originally store event IDs, and I learned the hard way that state idempotency ≠ side-effect idempotency. What's on the backlog now: a small processed\_events table (event\_id PK, type, created\_at, processed\_at). Handler checks it first and returns 200 early on duplicates, plus an ordering guard — only apply if event.created is newer than the last applied timestamp for that subscription, so a stale retry can't overwrite fresher state under concurrent delivery. Since you're pre-payments on Supabase, the combo I'd wire from day one: (1) verify signatures, (2) re-fetch live state, (3) event-ID store for side effects. It's maybe 30 lines of Edge Function and it deletes an entire class of 2 AM bugs. Happy to share my handler skeleton if it's useful — good luck with the wiring, it's about to get interesting!](https://hashnode.com/posts/why-stripe-test-mode-lies-a-solo-dev-s-36-hour-payment-infrastructure-trench-warfare/6accab3a2cf2ed754311386a/comment/6ace1152f4ebcd481f9cbcb9#reply-6ace11ef342d15a038821ba4)

Reply · Article · Oct 13 · [Why Stripe Test Mode Lies: A Solo Dev's 36-Hour Payment Infrastructure Trench Warfare](https://hashnode.com/posts/why-stripe-test-mode-lies-a-solo-dev-s-36-hour-payment-infrastructure-trench-warfare/6accab3a2cf2ed754311386a)
