Subscription Billing in Next.js: Trials, Upgrades, Cancellations, and Dunning
The subscription model is recurring revenue at the cost of recurring complexity. Upgrades, downgrades, trials, cancellations, failed payments -- each scenario needs to work correctly. Here's how to...

Source: DEV Community
The subscription model is recurring revenue at the cost of recurring complexity. Upgrades, downgrades, trials, cancellations, failed payments -- each scenario needs to work correctly. Here's how to implement it properly. The State Machine A subscription has well-defined states. Modeling them explicitly prevents bugs: type SubscriptionStatus = | "none" // No subscription, free tier | "trialing" // In trial period | "active" // Paying, current | "past_due" // Payment failed, grace period | "canceled" // Canceled, access until period end | "expired" // No access function hasAccess(user: User): boolean { switch (user.subscriptionStatus) { case "trialing": case "active": return true case "past_due": return true // Grace period -- still has access case "canceled": // Has access until the period ends return user.stripeCurrentPeriodEnd ? user.stripeCurrentPeriodEnd > new Date() : false case "none": case "expired": default: return false } } The Database Schema model User { id String @id @def