Athar Ahmad’s Stripe Billing Architecture for Bubble.io SaaS
Most Bubble Stripe integrations fail because they update subscription status from the redirect URL. Athar’s webhook-first principle, all six webhook events with their exact handlers, the complete billing data model, and the five-trigger test protocol that confirms billing is correct before any live customer pays.
Why Most Bubble Stripe Integrations Fail (And What Athar Does Instead)
Stripe billing is the most commercially critical part of any SaaS product. It is also the part most Bubble developers implement incorrectly. The most common mistake: updating subscription status from the checkout redirect URL. This causes 10-15% of successful payments to not activate the account, because the redirect can fail, be interrupted, or fire before Stripe has processed the payment. Athar Ahmad has implemented Stripe billing on over a dozen production Bubble SaaS applications. This is his architecture.
The Rule That Prevents Billing Incidents
The Complete Billing Architecture
| Webhook Event | When It Fires | What Athar’s Workflow Does |
|---|---|---|
| checkout.session.completed | Customer completes Stripe Checkout | Find workspace via metadata[workspace_id]. Set subscription_status=Active. Set stripe_sub_id. Set plan from price ID. Send welcome-to-paid email. |
| customer.subscription.updated | Plan change, pause, resume, or modification | Update subscription_status and plan from event data. Handle trial-to-paid conversion. Handle pause/resume transitions. |
| customer.subscription.deleted | Subscription cancelled (immediately or at period end) | Set subscription_status=Cancelled. Set cancelled_at. Preserve all data. Show reactivation CTA in app. Send cancellation confirmation email. |
| invoice.payment_failed | Automatic payment attempt fails | Set subscription_status=Past_Due. Set payment_failed_at. Show urgent payment update banner inside the app. Send failed payment email with update link. |
| invoice.payment_succeeded | Payment confirmed successfully | Set subscription_status=Active (if was Past_Due). Update current_period_end. Send payment receipt email. |
| customer.subscription.trial_will_end | 3 days before trial ends | Schedule trial-ending email sequence. Show upgrade prompts in app. Set trial_ending_soon flag on Workspace. |
Fields on Workspace That Track Everything
subscription_status
option set: Trialing / Active / Past_Due / Cancelled / Paused
plan
-> Plan data type
stripe_customer_id
text (created when workspace is created)
stripe_sub_id
text (set by checkout.session.completed)
trial_ends_at
date (set on workspace creation)
current_period_end
date (updated by invoice.payment_succeeded)
payment_failed_at
date (set by invoice.payment_failed)
cancelled_at
date (set by subscription.deleted)
mrr
number (monthly revenue, updated by webhooks)
// The checkout session: metadata links payment to workspace
metadata[workspace_id]
= Workspace’s Unique ID
// The webhook finds the workspace: Search for Workspaces where Unique ID = event.metadata.workspace_id
Athar’s Billing Test Protocol
stripe trigger checkout.session.completed
# activates trial
stripe trigger invoice.payment_succeeded
# confirms payment
stripe trigger invoice.payment_failed
# puts in past_due
stripe trigger customer.subscription.deleted
# cancels
stripe trigger customer.subscription.trial_will_end
# triggers warning
// After each trigger: check the Workspace record in Bubble Data tab
// Verify the subscription_status field updated correctly
// Verify the email sent to the test user
// DO NOT launch until all five tests pass
Work With Athar Ahmad
Pakistan’s leading Bubble.io systems architect. Multi-tenant SaaS architecture, Stripe billing, AI integration, and full product builds designed and delivered with precision.