@company-manager/docs

Renewal & Cancellation

Subscription renewal flows, cancellation handling, and win-back diagrams

Renewal & Cancellation

This page covers subscription renewal processes, cancellation flows, and customer retention strategies.

Renewal Flow Overview

flowchart TD
    subgraph "Pre-Renewal"
        APPROACH[Renewal Date Approaching] --> REMIND[Send Reminder]
        REMIND --> CHECK{Auto-Renew?}
    end

    subgraph "Auto-Renewal"
        CHECK -->|Yes| BILL[Generate Invoice]
        BILL --> PAY[Process Payment]
        PAY --> SUCCESS{Success?}
        SUCCESS -->|Yes| EXTEND[Extend Subscription]
        SUCCESS -->|No| RETRY[Enter Dunning]
    end

    subgraph "Manual Renewal"
        CHECK -->|No| NOTIFY[Send Renewal Notice]
        NOTIFY --> WAIT[Wait for Action]
        WAIT --> ACTION{User Action?}
        ACTION -->|Renew| MANUAL_PAY[Process Payment]
        ACTION -->|No Action| EXPIRE[Subscription Expires]
        MANUAL_PAY --> EXTEND
    end

    EXTEND --> CONFIRM[Send Confirmation]
    EXPIRE --> WINBACK[Win-Back Campaign]

    style EXTEND fill:#e8f5e9
    style EXPIRE fill:#ffebee

Auto-Renewal Sequence

sequenceDiagram
    participant Cron as Scheduler
    participant Service as Subscription Service
    participant Stripe as Stripe API
    participant DB as Database
    participant Email as Email Service
    participant User

    Note over Cron: Billing date reached

    Cron->>Service: processRenewals()
    Service->>DB: Get subscriptions due for renewal
    DB-->>Service: Subscriptions list

    loop For each subscription
        Service->>Stripe: Create invoice
        Stripe-->>Service: Invoice created

        Service->>Stripe: Pay invoice
        Stripe-->>Service: Payment result

        alt Payment successful
            Service->>DB: Extend subscription period
            Service->>DB: Update nextBillingDate
            Service->>Email: sendRenewalConfirmation()
            Email->>User: "Subscription renewed"
        else Payment failed
            Service->>DB: Mark as past_due
            Service->>Service: Schedule retry
            Service->>Email: sendPaymentFailedNotice()
            Email->>User: "Payment failed"
        end
    end

Renewal Reminder Timeline

gantt
    title Renewal Reminder Schedule
    dateFormat YYYY-MM-DD
    axisFormat %b %d

    section Reminders
    30-day reminder     :milestone, r30, 2024-01-01, 0d
    14-day reminder     :milestone, r14, 2024-01-17, 0d
    7-day reminder      :milestone, r7, 2024-01-24, 0d
    3-day reminder      :milestone, r3, 2024-01-28, 0d

    section Renewal
    Renewal Date        :crit, milestone, renewal, 2024-01-31, 0d

Cancellation Flow

flowchart TD
    REQUEST[Cancel Request] --> AUTH[Verify Authorization]
    AUTH --> CHECK{Immediate or End of Period?}

    CHECK -->|Immediate| IMMEDIATE[Cancel Now]
    CHECK -->|End of Period| SCHEDULE[Schedule Cancellation]

    IMMEDIATE --> PRORATE{Prorate Refund?}
    PRORATE -->|Yes| REFUND[Calculate & Issue Refund]
    PRORATE -->|No| REVOKE[Revoke Access]

    REFUND --> REVOKE

    SCHEDULE --> MARK[Mark for Cancellation]
    MARK --> CONTINUE[Continue Access Until End]
    CONTINUE --> END_DATE[End Date Reached]
    END_DATE --> REVOKE

    REVOKE --> STRIPE[Update Stripe]
    STRIPE --> DB[Update Database]
    DB --> EMAIL[Send Confirmation]
    EMAIL --> SURVEY[Send Exit Survey]

    SURVEY --> WINBACK[Add to Win-Back List]

    style REVOKE fill:#ffebee

Cancellation Sequence

sequenceDiagram
    participant User
    participant UI as Frontend
    participant API as TRPC Router
    participant Service as Subscription Service
    participant Stripe as Stripe API
    participant DB as Database
    participant Email as Email Service

    User->>UI: Click Cancel
    UI->>UI: Show cancellation options

    alt Retention Offer
        UI->>User: Show discount offer
        User->>UI: Accept/Decline
        alt Accepts offer
            UI->>API: applyRetentionOffer()
            Note over User: User retained
        end
    end

    User->>UI: Confirm cancellation
    UI->>API: cancelSubscription(id, options)
    API->>Service: cancelSubscription(id, immediate, reason)

    Service->>DB: Get subscription
    DB-->>Service: Subscription data

    alt Immediate cancellation
        Service->>Stripe: Cancel immediately
        Service->>Service: Calculate prorated refund
        Service->>Stripe: Issue refund
    else End of period
        Service->>Stripe: Cancel at period end
    end

    Stripe-->>Service: Cancelled

    Service->>DB: Update status (CANCELLED)
    Service->>DB: Log cancellation reason
    DB-->>Service: Updated

    Service->>Email: sendCancellationConfirmation()
    Email->>User: "Sorry to see you go"

    Service->>Email: scheduleExitSurvey()

    Service-->>API: Cancellation complete
    API-->>UI: Success

Cancellation Reasons Tracking

pie title Cancellation Reasons
    "Too expensive" : 35
    "Not using enough" : 25
    "Missing features" : 15
    "Found alternative" : 10
    "Technical issues" : 8
    "Other" : 7

Retention Offer Flow

flowchart TD
    CANCEL_INTENT[Cancel Intent] --> ANALYZE[Analyze Customer]

    ANALYZE --> SEGMENT{Customer Segment}

    SEGMENT -->|High Value| OFFER_HIGH[Premium Retention Offer]
    SEGMENT -->|Medium Value| OFFER_MED[Standard Retention Offer]
    SEGMENT -->|Low Value| NO_OFFER[No Special Offer]

    OFFER_HIGH --> DISCOUNT_50[50% off 3 months]
    OFFER_HIGH --> PAUSE_OFFER[Free pause option]
    OFFER_HIGH --> DOWNGRADE[Downgrade to lower tier]

    OFFER_MED --> DISCOUNT_25[25% off 2 months]
    OFFER_MED --> PAUSE_OFFER

    NO_OFFER --> EXIT_SURVEY[Exit Survey Only]

    DISCOUNT_50 --> PRESENT[Present Offer]
    DISCOUNT_25 --> PRESENT
    PAUSE_OFFER --> PRESENT
    DOWNGRADE --> PRESENT

    PRESENT --> RESPONSE{User Response}
    RESPONSE -->|Accept| APPLY[Apply Offer]
    RESPONSE -->|Decline| PROCEED[Proceed with Cancel]

    EXIT_SURVEY --> PROCEED

    APPLY --> RETAINED[Customer Retained]
    PROCEED --> CANCELLED[Subscription Cancelled]

    style RETAINED fill:#e8f5e9
    style CANCELLED fill:#ffebee

Win-Back Campaign Flow

sequenceDiagram
    participant System as Win-Back System
    participant DB as Database
    participant Email as Email Service
    participant User
    participant API as TRPC Router

    Note over System: Day 7 after cancellation

    System->>DB: Get recently cancelled
    DB-->>System: Cancelled subscribers

    System->>Email: sendWinBackEmail1()
    Email->>User: "We miss you" + offer

    Note over System: Day 14

    System->>DB: Check if resubscribed
    DB-->>System: Still cancelled

    System->>Email: sendWinBackEmail2()
    Email->>User: "Special offer just for you"

    Note over System: Day 30

    System->>DB: Check if resubscribed
    DB-->>System: Still cancelled

    System->>Email: sendWinBackEmail3()
    Email->>User: "Last chance for discount"

    alt User clicks resubscribe
        User->>API: resubscribe(offerId)
        API->>System: applyWinBackOffer()
        System->>DB: Create new subscription
        System->>Email: sendWelcomeBack()
    end

Expiration Handling

stateDiagram-v2
    ACTIVE --> EXPIRING: 30 days before end
    EXPIRING --> EXPIRED: End date reached

    state EXPIRING {
        [*] --> REMINDER_30
        REMINDER_30 --> REMINDER_14: 14 days left
        REMINDER_14 --> REMINDER_7: 7 days left
        REMINDER_7 --> REMINDER_1: 1 day left
        REMINDER_1 --> [*]
    }

    EXPIRED --> GRACE: Grace period start
    GRACE --> TERMINATED: Grace period ends
    GRACE --> ACTIVE: Renewal payment

    TERMINATED --> WINBACK: Win-back campaign
    WINBACK --> ACTIVE: Resubscribe
flowchart TD
    subgraph "Tracking"
        TRACK[Track Issues Delivered] --> COUNT[Count Remaining]
        COUNT --> CHECK{Issues Remaining?}
    end

    subgraph "Low Issue Alert"
        CHECK -->|Few left| ALERT[Send Renewal Notice]
        ALERT --> OFFER[Include Renewal Offer]
    end

    subgraph "Renewal"
        CHECK -->|Renew| PAYMENT[Process Payment]
        PAYMENT --> ADD[Add Issues to Subscription]
        ADD --> CONTINUE[Continue Deliveries]
    end

    subgraph "Expiration"
        CHECK -->|No renewal| LAST[Deliver Last Issue]
        LAST --> EXPIRE[Mark Expired]
        EXPIRE --> FINAL[Send Final Notice]
    end

    style CONTINUE fill:#e8f5e9
    style EXPIRE fill:#ffebee

Subscription Recovery Metrics

flowchart LR
    subgraph "Funnel"
        CANCELLED[Cancelled]
        CONTACTED[Contacted]
        ENGAGED[Engaged with Offer]
        RECOVERED[Recovered]
    end

    CANCELLED --> CONTACTED
    CONTACTED --> ENGAGED
    ENGAGED --> RECOVERED

    subgraph "Metrics"
        RATE1[Contact Rate: 100%]
        RATE2[Engagement Rate: 35%]
        RATE3[Recovery Rate: 15%]
    end