Group
  • Payments

    Model subscription states correctly

    Implements the real subscription lifecycle (trialing, active, past_due, canceled) with access rules per state.

    • Improve quality
    • Plan & validate
    • Intermediate
    • General

Free Prompt

Audit how my app represents subscription state and align it with how the payment provider actually models it. Check the subscription record, the access-control logic, and every webhook that mutates state. Implement a real state model: trialing (full access, card may or may not be on file, ends at trial end), active (paying, full access), past_due (payment failed, retries in progress, access policy decided deliberately: grace period or immediate downgrade), canceled (no renewal, access until paid-through date or immediately, decided deliberately), and incomplete (checkout started but payment never confirmed). Store the provider's subscription ID and the paid-through date, and derive access from state plus dates, not from a single boolean. Handle the transitions from provider webhooks only (payment succeeded, payment failed, canceled, trial ending), never from client requests. Decide and document what 'cancel' means: end of paid period is the standard users expect. Don't let users' access depend on fields the client can influence. Don't hard-delete subscription records on cancel; they're billing history. Deliver: the state model with transition map, the access rule per state, the webhook wiring per transition, and a test pass through the lifecycle: start trial, convert to paid, fail a payment, recover, cancel, and confirm access matches the documented rule at each step.

What This Does / How This Helps

Replaces the single 'subscribed: true/false' flag with the actual states subscriptions live in, and defines what access each state grants. A boolean can't express the situations that matter: the card that failed Tuesday but might succeed Friday, the user who canceled but paid through the end of the month, the trial that ends tonight. Apps with a boolean handle these by accident: cutting off paying customers during a retry, or giving canceled users free months forever. The lifecycle test pass proves the whole loop, including the past_due recovery that determines whether a temporary card problem becomes a lost customer.

Want to skip doing this by hand?

Fortivibe audits your app for all of the areas these prompts cover (and more).

See What We Check

Related Prompts