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:#ffebeeAuto-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
endRenewal 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, 0dCancellation 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:#ffebeeCancellation 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: SuccessCancellation Reasons Tracking
pie title Cancellation Reasons
"Too expensive" : 35
"Not using enough" : 25
"Missing features" : 15
"Found alternative" : 10
"Technical issues" : 8
"Other" : 7Retention 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:#ffebeeWin-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()
endExpiration 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: ResubscribePrint Subscription Renewal
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:#ffebeeSubscription 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