Billing Cycles
Recurring billing, invoice generation, and payment processing diagrams
Billing Cycles
This page covers the recurring billing process including invoice generation, payment collection, and retry logic.
Billing Cycle Overview
flowchart TD
subgraph "Billing Trigger"
SCHEDULE[Scheduled Billing Date] --> CHECK[Check Active Subscriptions]
CHECK --> DUE[Find Due Subscriptions]
end
subgraph "Invoice Generation"
DUE --> CREATE[Create Invoice]
CREATE --> CALCULATE[Calculate Amount]
CALCULATE --> APPLY[Apply Discounts/Credits]
APPLY --> FINALIZE[Finalize Invoice]
end
subgraph "Payment"
FINALIZE --> CHARGE[Attempt Payment]
CHARGE --> RESULT{Payment Result}
RESULT -->|Success| PAID[Mark Paid]
RESULT -->|Failure| RETRY[Schedule Retry]
end
subgraph "Post-Payment"
PAID --> UPDATE[Update Subscription]
UPDATE --> NEXT[Set Next Billing Date]
NEXT --> NOTIFY[Send Receipt]
end
RETRY --> DUNNING[Enter Dunning Flow]
style PAID fill:#e8f5e9
style RETRY fill:#ffebeeInvoice Generation Sequence
sequenceDiagram
participant Cron as Billing Scheduler
participant Service as Billing Service
participant DB as Database
participant Stripe as Stripe API
participant Email as Email Service
Cron->>Service: runBillingCycle()
Service->>DB: Get subscriptions due for billing
Note over Service,DB: WHERE nextBillingDate <= NOW()
DB-->>Service: Due subscriptions
loop For each subscription
Service->>Service: Calculate invoice amount
Note over Service: Base price + add-ons - credits
Service->>DB: Create SubscriptionInvoice (PENDING)
DB-->>Service: Invoice created
Service->>Stripe: Create invoice
Note over Stripe: Linked to Stripe customer
Stripe-->>Service: Stripe invoice
Service->>Stripe: Finalize and pay invoice
Stripe-->>Service: Payment result
alt Payment successful
Service->>DB: Update invoice (PAID)
Service->>DB: Update nextBillingDate
Service->>Email: sendReceipt(invoice)
else Payment failed
Service->>DB: Update invoice (FAILED)
Service->>DB: Update subscription (PAST_DUE)
Service->>DB: Schedule retry
end
end
Service-->>Cron: Billing cycle completeInvoice State Machine
stateDiagram-v2
[*] --> DRAFT: Create Invoice
DRAFT --> PENDING: Finalize
DRAFT --> VOID: Cancel
PENDING --> PAID: Payment Success
PENDING --> FAILED: Payment Failed
PENDING --> VOID: Cancel
FAILED --> PENDING: Retry Payment
FAILED --> PAID: Retry Success
FAILED --> UNCOLLECTIBLE: Max Retries
PAID --> REFUNDED: Full Refund
PAID --> PARTIALLY_REFUNDED: Partial Refund
VOID --> [*]
PAID --> [*]
UNCOLLECTIBLE --> [*]
REFUNDED --> [*]Amount Calculation Flow
flowchart TD
START[Calculate Invoice] --> BASE[Get Base Plan Price]
BASE --> ADDONS{Add-ons?}
ADDONS -->|Yes| CALC_ADDONS[Calculate Add-on Amounts]
ADDONS -->|No| SUBTOTAL1
CALC_ADDONS --> SUBTOTAL1[Subtotal]
SUBTOTAL1 --> DISCOUNTS{Discounts?}
DISCOUNTS -->|Coupon| APPLY_COUPON[Apply Coupon Discount]
DISCOUNTS -->|Promo| APPLY_PROMO[Apply Promo Code]
DISCOUNTS -->|None| SUBTOTAL2
APPLY_COUPON --> SUBTOTAL2[Subtotal After Discounts]
APPLY_PROMO --> SUBTOTAL2
SUBTOTAL2 --> CREDITS{Account Credits?}
CREDITS -->|Yes| APPLY_CREDITS[Apply Credits]
CREDITS -->|No| TAX
APPLY_CREDITS --> TAX[Calculate Tax]
TAX --> TOTAL[Final Total]
subgraph "Example"
EX_BASE[Plan: €29.00]
EX_ADD[+ Add-on: €10.00]
EX_SUB1[= €39.00]
EX_DISC[- 20% coupon: €7.80]
EX_SUB2[= €31.20]
EX_CRED[- Credit: €5.00]
EX_SUB3[= €26.20]
EX_TAX[+ VAT 20%: €5.24]
EX_TOTAL[Total: €31.44]
end
style TOTAL fill:#e8f5e9Proration Calculation
flowchart TD
CHANGE[Mid-Cycle Change] --> TYPE{Change Type}
TYPE -->|Upgrade| UPGRADE[Calculate Upgrade Proration]
TYPE -->|Downgrade| DOWNGRADE[Calculate Downgrade Proration]
TYPE -->|Add-on Added| ADDON_ADD[Prorate Add-on]
TYPE -->|Add-on Removed| ADDON_REM[Credit Remaining]
subgraph "Upgrade Proration"
UPGRADE --> DAYS_LEFT[Days Remaining in Cycle]
DAYS_LEFT --> DIFF[Price Difference]
DIFF --> PRORATE_CHARGE[Charge = (Diff / Total Days) × Days Left]
end
subgraph "Downgrade Proration"
DOWNGRADE --> DAYS_LEFT2[Days Remaining]
DAYS_LEFT2 --> DIFF2[Price Difference]
DIFF2 --> PRORATE_CREDIT[Credit = (Diff / Total Days) × Days Left]
end
PRORATE_CHARGE --> APPLY[Apply to Next Invoice]
PRORATE_CREDIT --> APPLY
ADDON_ADD --> APPLY
ADDON_REM --> APPLYPayment Retry Flow (Dunning)
stateDiagram-v2
[*] --> INITIAL_FAIL: Payment Fails
INITIAL_FAIL --> RETRY_1: Wait 1 day
RETRY_1 --> RETRY_2: Fail, wait 3 days
RETRY_1 --> SUCCESS: Payment Success
RETRY_2 --> RETRY_3: Fail, wait 5 days
RETRY_2 --> SUCCESS: Payment Success
RETRY_3 --> RETRY_4: Fail, wait 7 days
RETRY_3 --> SUCCESS: Payment Success
RETRY_4 --> CANCEL: Fail, max retries
RETRY_4 --> SUCCESS: Payment Success
SUCCESS --> ACTIVE: Subscription Active
CANCEL --> CANCELLED: Subscription Cancelled
note right of RETRY_1: Email: Payment failed
note right of RETRY_2: Email: Action required
note right of RETRY_3: Email: Final warning
note right of RETRY_4: Email: Subscription cancelledDunning Email Sequence
sequenceDiagram
participant System as Billing System
participant Email as Email Service
participant User
Note over System: Payment fails
System->>Email: Send payment failed email
Email->>User: "Your payment failed"
Note over User: Day 0
System->>System: Wait 1 day, retry payment
Note over System: Retry 1 fails
System->>Email: Send reminder email
Email->>User: "Please update payment method"
Note over User: Day 1
System->>System: Wait 3 days, retry payment
Note over System: Retry 2 fails
System->>Email: Send urgent email
Email->>User: "Service may be interrupted"
Note over User: Day 4
System->>System: Wait 5 days, retry payment
Note over System: Retry 3 fails
System->>Email: Send final warning
Email->>User: "Last chance to update payment"
Note over User: Day 9
System->>System: Wait 7 days, final retry
Note over System: Final retry fails
System->>Email: Send cancellation notice
Email->>User: "Subscription cancelled"
Note over User: Day 16Billing Interval Types
flowchart LR
subgraph "Interval Options"
DAILY[Daily]
WEEKLY[Weekly]
MONTHLY[Monthly]
QUARTERLY[Quarterly]
YEARLY[Yearly]
end
subgraph "Next Billing Calculation"
DAILY --> NEXT_DAY[+1 day]
WEEKLY --> NEXT_WEEK[+7 days]
MONTHLY --> NEXT_MONTH[+1 month]
QUARTERLY --> NEXT_QUARTER[+3 months]
YEARLY --> NEXT_YEAR[+1 year]
endMulti-Currency Billing
flowchart TD
CUSTOMER[Customer Currency] --> DETERMINE{Determine Billing Currency}
DETERMINE --> PLAN_CURR[Plan Default Currency]
DETERMINE --> CUST_PREF[Customer Preference]
DETERMINE --> GEO[Geographic Detection]
PLAN_CURR --> SELECT[Select Currency]
CUST_PREF --> SELECT
GEO --> SELECT
SELECT --> CONVERT{Conversion Needed?}
CONVERT -->|Yes| RATE[Get Exchange Rate]
CONVERT -->|No| CHARGE[Charge in Currency]
RATE --> CALCULATE[Calculate Converted Amount]
CALCULATE --> CHARGE
CHARGE --> STRIPE[Process via Stripe]Subscription Invoice ERD
erDiagram
SUBSCRIPTION ||--o{ SUBSCRIPTION_INVOICE : generates
SUBSCRIPTION_INVOICE ||--o{ INVOICE_LINE_ITEM : contains
SUBSCRIPTION_INVOICE }o--o| PAYMENT_TRANSACTION : paid_by
SUBSCRIPTION_INVOICE }o--o| COUPON : applies
SUBSCRIPTION_INVOICE {
string id PK
string subscriptionId FK
string invoiceNumber
decimal subtotal
decimal discount
decimal tax
decimal total
string currency
enum status
timestamp periodStart
timestamp periodEnd
timestamp dueDate
timestamp paidDate
string stripeInvoiceId
int retryCount
timestamp nextRetryDate
}
INVOICE_LINE_ITEM {
string id PK
string invoiceId FK
string description
int quantity
decimal unitPrice
decimal amount
enum itemType
}Billing Analytics
flowchart LR
subgraph "Data Collection"
INVOICES[Invoices]
PAYMENTS[Payments]
FAILURES[Failed Payments]
end
subgraph "Metrics"
MRR[MRR Calculation]
CHURN[Churn Rate]
ARPU[ARPU]
LTV[Customer LTV]
end
subgraph "Reports"
REV[Revenue Report]
COHORT[Cohort Analysis]
FORECAST[Revenue Forecast]
end
INVOICES --> MRR
INVOICES --> ARPU
PAYMENTS --> MRR
FAILURES --> CHURN
MRR --> REV
CHURN --> COHORT
ARPU --> LTV
LTV --> FORECAST