SaaS Billing & Subscriptions — SKILL.md
Raw skill file that agents receive when using this skill
---
name: "SaaS Billing & Subscriptions"
description: "Implement SaaS billing: Stripe Billing (Products, Prices, Subscriptions), subscription lifecycle, dunning (failed payments), tax handling (Stripe Tax, Paddle MoR), metered/usage billing, enterprise invoicing, revenue recognition, and MRR/churn metrics."
version: "1.0.0"
author: "skynet"
category: "dev"
agents: ["claude-code", "codex", "gemini"]
tags: ["saas", "billing", "stripe", "subscriptions", "payments", "mrr"]
---
# SaaS Billing & Subscriptions
---
name: "SaaS Billing & Subscriptions"
description: "Implement SaaS billing: Stripe Billing (Products, Prices, Subscriptions), subscription lifecycle, dunning (failed payments), tax handling (Stripe Tax, Paddle MoR), metered/usage billing, enterprise in"
version: "1.0.0"
author: "skynet"
category: "dev"
tags: ["saas", "billing", "stripe", "subscriptions", "payments", "mrr"]
---
# SaaS Billing & Subscription Management: Technical Reference
Implementing billing is one of the most critical and complex components of a SaaS architecture. It requires high consistency, security, and a deep understanding of the subscription lifecycle.
## 1. Billing Models
| Model | Description | Technical Implementation |
| :--- | :--- | :--- |
| **Flat Subscription** | Fixed price per interval (e.g., $50/mo). | Single `Price` attached to a `Subscription`. |
| **Per-Seat** | Price multiplied by quantity of users. | `SubscriptionItem` with a `quantity` field; update via webhooks when users are added/removed. |
| **Usage-Based** | Pay for consumption (e.g., per API call). | `Price` with `usage_type=metered`. Requires reporting usage records to the provider. |
| **Credits/Prepaid** | Users buy tokens/credits upfront. | Internal ledger in your DB; decremented as used. Often integrated with "top-up" one-time purchases. |
| **Hybrid** | Base platform fee + usage overages. | Multiple `Prices` on one `Subscription`: one fixed, one metered. |
| **Add-ons** | Optional features (e.g., "Priority Support"). | Supplemental `SubscriptionItems` or one-time `InvoiceItems`. |
---
## 2. Stripe Billing Architecture
Stripe is the industry standard for developer-first billing. Its object hierarchy is:
`Customer` -> `Product` -> `Price` -> `Subscription`.
### Subscription Lifecycle States
- **`trialing`**: Active but not yet billed.
- **`active`**: Payment successful, service granted.
- **`past_due`**: Renewal failed; entering dunning.
- **`unpaid`**: Dunning failed; service usually revoked here.
- **`canceled`**: Explicitly terminated.
- **`incomplete`**: First payment failed (for SCA/3D Secure flows).
### Stripe Implementation (Node.js)
```typescript
// Create a Checkout Session for a new subscription
const session = await stripe.checkout.sessions.create({
customer: 'cus_123',
payment_method_types: ['card'],
line_items: [{ price: 'price_H5ggfxyz', quantity: 1 }],
mode: 'subscription',
success_url: 'https://app.com/success?session_id={CHECKOUT_SESSION_ID}',
cancel_url: 'https://app.com/canceled',
subscription_data: { trial_period_days: 14 },
});
```
---
## 3. Alternative Platforms
### Merchant of Record (MoR)
MoRs take legal responsibility for the transaction, handling global sales tax, VAT, and compliance.
- **Paddle**: Excellent for global SaaS; handles all VAT/GST. Unified billing/overlay.
- **LemonSqueezy**: High-growth MoR; very indie-friendly, simpler API than Stripe.
### Enterprise & Management Layers
- **Chargebee / Recurly**: Orchestration layers that sit on top of gateways (Stripe/Adyen). Provide advanced revenue recognition and complex logic.
- **Maxio**: Focused on B2B SaaS metrics and financial operations.
---
## 4. Subscription Lifecycle Management
### Proration Strategies
When a user switches plans mid-cycle:
1. **Always Invoice**: Immediately charge/credit the difference.
2. **Defer to Next Cycle**: Calculate the difference but apply it to the next invoice.
3. **No Proration**: Simple "switch at end of period."
**Stripe Proration Example:**
```typescript
const subscription = await stripe.subscriptions.update('sub_123', {
items: [{
id: 'si_abc', // existing item
price: 'price_new_premium',
}],
proration_behavior: 'always_invoice', // Charge immediately
});
```
---
## 5. Dunning & Failed Payments
Dunning is the process of communicating with customers to recover failed payments.
- **Smart Retries**: Stripe's "Smart Retries" use ML to attempt charges at optimal times.
- **Grace Periods**: Allow 3–7 days of access while `past_due`.
- **Card Updater**: Stripe/Braintree automatically update expired card details via network partnerships.
- **Webhook Workflow**:
- `invoice.payment_failed` -> Send "Action Required" email.
- `customer.subscription.updated` (status: `unpaid`) -> Revoke app access.
---
## 6. Tax Handling
SaaS is taxable in most jurisdictions (Nexus in US, VAT in EU).
- **Stripe Tax**: Automatically calculates and collects tax based on customer address.
- **TaxJar / Avalara**: Specialized tax engines for complex nexus scenarios.
- **The MoR Advantage**: If using Paddle/LemonSqueezy, you don't need these; they act as the seller and remit all taxes.
---
## 7. Metered Billing (Usage Tracking)
**Pattern: Event-Based Reporting**
Don't calculate the bill yourself. Send "events" to Stripe and let it aggregate.
```typescript
// Report 50 units of "API Calls" used today
await stripe.subscriptionItems.createUsageRecord('si_123', {
quantity: 50,
timestamp: Math.floor(Date.now() / 1000),
action: 'increment', // 'set' replaces the previous value
});
```
- **Aggregation**: Choose `sum` (total units), `last_during_period` (current state), or `max`.
---
## 8. Enterprise Billing Requirements
Enterprise customers rarely use credit cards.
- **Invoice Billing**: Payment terms like **Net 30** or **Net 60**.
- **Purchase Orders (PO)**: Requiring a PO number on the generated PDF.
- **Custom Contracts**: Negotiated pricing that doesn't exist on your public pricing page (use "Ad-hoc" prices in Stripe).
- **Consolidated Billing**: One "Parent" company paying for multiple "Child" departments/entities.
---
## 9. Key SaaS Metrics (The "North Stars")
- **MRR / ARR**: Monthly/Annual Recurring Revenue.
- **Churn Rate**:
- **Logo Churn**: % of customers leaving.
- **Revenue Churn**: % of MRR lost.
- **Net Revenue Retention (NRR)**: (Starting MRR + Expansion - Contraction - Churn) / Starting MRR. Target > 100%.
- **LTV (Lifetime Value)**: `ARPU (Average Revenue Per User) / Churn Rate`.
- **CAC (Customer Acquisition Cost)**: Total Sales & Marketing / New Customers.
---
## 10. Revenue Recognition (ASC 606)
Under ASC 606, you cannot recognize a $1,200 annual payment the day you receive it.
- **Deferred Revenue**: The $1,100 remaining after month 1.
- **Recognized Revenue**: $100 per month for 12 months.
- **Implementation**: Ensure your billing system (or a tool like ProfitWell/ChartMogul) handles the "Earned vs. Unearned" logic for accounting compliance.
---
## 11. Architectural Best Practices
1. **Webhook Idempotency**: Stripe may send the same webhook twice. Always check `event.id` against a processed events table in your DB.
2. **Don't Store CC Data**: Use Stripe Elements or Checkout. Your servers should never see raw card numbers (PCI compliance).
3. **Sync State via Webhooks**: Your DB should be a "read-only" mirror of Stripe's state for fast authorization checks (e.g., `user.is_subscribed = true`).
4. **The "Portal" Pattern**: Use the **Stripe Customer Portal** to outsource 90% of your self-service UI (changing plans, updating cards, downloading invoices).
```typescript
// Generate a link to the hosted Customer Portal
const portalSession = await stripe.billingPortal.sessions.create({
customer: 'cus_123',
return_url: 'https://app.com/settings',
});
// Redirect user to portalSession.url
```
curl -s https://skills.skynet.ceo/api/skills/saas-billing-subscriptions/skill.md