Skip to content

fix(payments): add reconciliation for missed Dodo renewal webhooks #4765

Description

@koala73

Validated on current origin/main (5139377).

Finding:

  • Convex payment state updates entitlements when Dodo webhook events arrive.
  • subscription.renewed updates subscriptions.currentPeriodEnd and recomputes entitlements in convex/payments/subscriptionHelpers.ts.
  • convex/crons.ts has maintenance crons, but no subscription-renewal reconciliation cron that queries Dodo for active subscriptions whose local currentPeriodEnd has passed.

Impact:

  • If a renewal webhook is missed or exhausted after retries, a paying subscriber can be silently downgraded once the stale local validUntil expires, even if Dodo still considers the subscription active.

Suggested fix:

  • Add a daily reconciliation job for active subscriptions with currentPeriodEnd < now.
  • Query Dodo for authoritative state, refresh subscription rows, and recompute entitlements.
  • Add a regression test covering an active remote subscription with stale local period end and no recent webhook.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpaymentPayment, billing, subscription, checkout, and entitlement lifecycle

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions