Skip to content

gap: no self-serve plan upgrade/change flow for existing subscribers (Starter→Business; blocks #3199 enforce + misses revenue) #4634

Description

@koala73

Part of the plan-limit upgrade lifecycle epic (#4635). This issue is the self-serve upgrade mechanism — the "way to upgrade" a customer needs once they're notified they're over their plan. (Detection + notification is a sibling issue; see the epic.)

Consent constraint: we must NOT auto-move a customer to a higher-priced plan — that charges them without consent. The customer must choose to upgrade (or reduce their traffic). So this flow is customer-initiated.

Current state (verified in code)

  • Checkout hard-blocks an active subscriber. convex/payments/checkout.ts returns ACTIVE_SUBSCRIPTION_EXISTS"use Manage Billing to update it." No upgrade/plan-change branch.
  • "Manage Billing" = a default Dodo customer-portal session. convex/payments/billing.ts:114customerPortal.create(id, { send_email:false }) — no plan-change params. Plan-switching is Dodo-dashboard config, not enabled/handled in code.
  • In-app "Upgrade" CTAs are all Free → Pro (DEFAULT_UPGRADE_PRODUCT = PRO_MONTHLY). No Starter → Business (API-tier) upgrade CTA.
  • Business isn't self-serve (selfServe:false, publicVisible:false, currentForCheckout:false); no outbound Dodo subscription-update/proration call exists (only inbound webhook).

Options (cheapest → most complete; decide in planning)

  • (a) Portal route: enable plan-switching in the Dodo customer portal + surface a "Change plan" entry point in-app. Verify Dodo supports it for this account.
  • (b) In-app upgrade flow: new action calling Dodo's subscription change/proration API + a "Change plan" UI on /pro and in-dashboard.
  • (c) Checkout upgrade: make Business self-serve and have checkout perform a plan-change (proration) instead of hard-blocking active subs.

Impact

Blocks the #3199 enforce rollout (over-cap Starter customers have no consent-based path to Business) and is a standing revenue-capture gap (customers who outgrow Starter can't upgrade in-product). Business is unreachable via checkout at all.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium priority, schedule when capacity allowsarea: APIBackend API, sidecar, keys

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions