Core Entities
Plan: plan_id, name, billing_cycle (MONTHLY, ANNUAL, WEEKLY), price_cents, currency, trial_days, features (JSON). Subscription: subscription_id, customer_id, plan_id, status (TRIALING, ACTIVE, PAST_DUE, CANCELLED, PAUSED), current_period_start, current_period_end, trial_end, cancel_at_period_end, payment_method_id. Invoice: invoice_id, subscription_id, customer_id, status (DRAFT, OPEN, PAID, VOID, UNCOLLECTIBLE), amount_due_cents, amount_paid_cents, period_start, period_end, due_date, paid_at. InvoiceItem: item_id, invoice_id, description, amount_cents, quantity, proration (boolean). PaymentAttempt: attempt_id, invoice_id, amount_cents, status (PENDING, SUCCEEDED, FAILED), failure_code, attempted_at.
Subscription Lifecycle
Trial: subscription starts in TRIALING for trial_days. No charge during trial. When trial ends: transition to ACTIVE and charge the first period. Active: charge at the start of each period. If payment succeeds: extend current_period_end by one billing cycle. If payment fails: transition to PAST_DUE, begin the dunning process. Cancellation: two modes: (1) cancel_at_period_end=true: subscription remains ACTIVE and customer keeps access until current_period_end, then cancels. (2) Immediate cancellation: prorate a refund for unused time and cancel immediately. Pause: temporarily suspend billing (customer keeps access, no charges). Resume on a future date. Used for seasonal subscriptions.
Proration Logic
When a customer upgrades mid-cycle: charge for the new plan from now until period_end, credit for the old plan from now until period_end. Proration formula: credit = old_price * (days_remaining / days_in_period). Charge = new_price * (days_remaining / days_in_period). Net charge = charge – credit. Always round up to the nearest cent. Example: $10/month plan, 15 days into a 30-day month, upgrades to $20/month. Credit = $10 * (15/30) = $5. Charge = $20 * (15/30) = $10. Net = $5 due immediately. Create an InvoiceItem with proration=true for the credit and another for the charge. Add to the current draft invoice (if mid-cycle) or the next invoice (end of cycle).
Dunning Management
Dunning: the process of recovering failed subscription payments. When a charge fails: update invoice status to OPEN, subscription status to PAST_DUE. Dunning schedule: retry Day 1, Day 3, Day 7, Day 14. On each retry: attempt payment via the saved payment method. If card expired: send an email asking the customer to update their payment method with a magic link. If retry succeeds: mark invoice PAID, restore subscription to ACTIVE. If all retries fail: mark invoice UNCOLLECTIBLE, cancel the subscription, send final cancellation email. Smart retry: retry when more likely to succeed — try on the day of the month the customer is most often successfully charged (analyze historical payment success by day). Avoid retrying on weekends. Use Stripe’s smart retries or implement the schedule with a cron job.
Metered / Usage-Based Billing
Some plans charge based on usage (API calls, GB stored, seats). Metered billing: track usage events during the billing period. Record every event: (subscription_id, metric, quantity, timestamp). At period end: aggregate total usage, compute the charge. Price tiers: first 1000 API calls free, $0.001 per call for 1001-100,000, $0.0005 per call above 100,000. Aggregation: a batch job runs at the end of each billing period, sums usage by tier, creates InvoiceItems for each tier. Real-time usage tracking: ingest usage events via API or Kafka. Store in a time-series DB. Provide customers a real-time usage dashboard with projected costs for the current period (prevent bill shock). Usage alerts: send an email when a customer has used 80% of their included quota.
Revenue Recognition
For annual subscriptions paid upfront: record the full payment as deferred revenue, recognize monthly (1/12 per month). This is required by GAAP (ASC 606). Technically: when a $120 annual subscription is paid: debit Cash $120, credit Deferred Revenue $120. Each month: debit Deferred Revenue $10, credit Revenue $10. Track current_period_revenue and deferred_revenue per subscription. Monthly revenue report: sum of all revenue recognized in the current month. This differs from cash collected in the month (new annual subscriptions inflate cash but not revenue). Expose both metrics for financial reporting.
Asked at: Stripe Interview Guide
Asked at: Shopify Interview Guide
Asked at: Netflix Interview Guide
Asked at: Atlassian Interview Guide
See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering
See also: Meta Interview Guide 2026: Facebook, Instagram, WhatsApp Engineering
See also: Coinbase Interview Guide