Subscriptions & Usage Billing

Pathrule2 Rules • 2 Memories • 1 Skill

A pattern bundle for subscription and usage-based billing on Stripe Billing in 2026. It covers Billing Meters and meter events, idempotent webhook handling, entitlement sync, proration on plan changes, and dunning for failed payments. Keep your own database as the source of truth for usage and entitlements, and treat Stripe events as a queue you reconcile against.

Suggested path map

Pathrule places each piece on the matching path, so your assistant only sees it where it belongs. This is the scoping you get on import; you can adjust it in your workspace.

/ workspace root
subscriptions-usage-billing-review
src/
usage/
Report usage through Billing Meters with idempotent meter events
api/
webhooks/
Verify, dedupe, and acknowledge Stripe webhooks before doing work
billing/
Entitlements are derived from subscription webhooks, not local guesses
Proration, seats, and dunning are configured in Stripe, not hand-rolled

Rules

2
Report usage through Billing Meters with idempotent meter events/src/usagehighstrictSend every usage event to a Billing Meter with a unique identifier and a valid timestamp.
1Meter all usage through Stripe Billing Meters and meter events; the legacy `usage_records` API is deprecated and must not be used for new code.
2 
3- Set a unique `identifier` on every meter event so retries dedupe inside Stripe's rolling 24 hour+ window; reuse the same identifier when you retry a failed send.
4- Keep the event `timestamp` within the past 35 days and no more than 5 minutes in the future, or Stripe rejects it.
5- For high throughput (over a few hundred events/sec) use the v2 meter event stream with a session token instead of one synchronous call per event.
6- Treat your own `usage_events` table as the source of truth; Stripe meter summaries are for billing, not for showing customers their live usage.
Verify, dedupe, and acknowledge Stripe webhooks before doing work/src/api/webhookshighstrictEvery Stripe webhook handler verifies the signature, is idempotent, and returns 2xx fast.
1Drive all billing state transitions from verified webhooks, never from browser redirects, because the user can close the tab before the redirect fires.
2 
3- Verify the signature with the raw request body and the endpoint secret; reject anything that fails before parsing.
4- Make handlers idempotent by recording processed `event.id` values and skipping duplicates, since Stripe can deliver the same event more than once.
5- Return a 2xx within seconds and offload slow work to a queue; long handlers cause Stripe retries and duplicate processing.
6- Subscribe to `v1.billing.meter.error_report_triggered` and alert on `meter_event_customer_not_found` spikes, which signal a broken usage integration silently dropping events.

Memories

2
Entitlements are derived from subscription webhooks, not local guesses/src/billingSync feature access from Stripe Entitlements events and gate features on stored entitlements.
1Stripe Entitlements expose what each customer can access based on their active subscription, and we mirror them locally rather than hardcoding plan-to-feature maps.
2 
3- On `customer.subscription.created`, `customer.subscription.updated`, `customer.subscription.deleted`, and `entitlements.active_entitlement_summary.updated`, refetch the customer's active entitlements and upsert them into our `entitlements` table.
4- Gate every paid feature on the stored entitlement lookup, not on the price ID or product name, so plan and packaging changes do not require code edits.
5- Treat `customer.subscription.deleted` and past-due states as access removal, but keep a short grace window driven by `status` rather than deleting rows immediately.
6- Reconcile nightly by listing live subscriptions and entitlements to heal any missed webhook.
Proration, seats, and dunning are configured in Stripe, not hand-rolled/src/billingLet Stripe handle proration math, seat quantity changes, and failed-payment recovery.
1Plan changes, seat counts, and recovery from failed payments are owned by Stripe Billing; we configure behavior and react to the resulting events.
2 
3- For upgrades and downgrades, update the subscription item and let Stripe compute proration (`proration_behavior`); never compute partial-period charges ourselves.
4- Model seats as a licensed (per-seat) subscription item quantity; adjust the quantity on team membership changes so proration applies automatically.
5- Enable Smart Retries for dunning (default schedule is 7 retries over 21 days) and react to `invoice.payment_failed`, `invoice.paid`, and `customer.subscription.updated` to flip account status.
6- Never store prices locally; always reference Stripe price IDs so amounts stay authoritative.

Skills

1
subscriptions-usage-billing-review/rootPre-merge checklist for any change touching metering, webhooks, entitlements, proration, or dunning.
1---
2name: subscriptions-usage-billing-review
3description: Review checklist for subscription and usage-based billing changes on Stripe Billing. Use before merging any code that records usage, handles billing webhooks, syncs entitlements, changes plans or seats, or touches dunning.
4---
5 
6# Subscriptions & usage billing review
7 
8- [ ] Usage is reported via Billing Meters and meter events, not the deprecated `usage_records` API.
9- [ ] Every meter event sets a unique `identifier` and is safe to retry without double counting.
10- [ ] Meter event timestamps fall within the past 35 days and under 5 minutes in the future.
11- [ ] High-volume metering uses the v2 meter event stream rather than one synchronous call per event.
12- [ ] A local `usage_events` ledger is written first and treated as the source of truth.
13- [ ] Webhook signatures are verified against the raw body and endpoint secret before parsing.
14- [ ] Webhook handlers are idempotent on `event.id` and tolerate duplicate delivery.
15- [ ] Handlers return 2xx quickly and push slow work to a queue.
16- [ ] `v1.billing.meter.error_report_triggered` is subscribed and alerts on `meter_event_customer_not_found`.
17- [ ] Entitlements are synced from subscription and entitlement-summary webhooks and feature gates read the stored entitlement, not the price ID.
18- [ ] Plan changes update the subscription item and let Stripe handle proration; no hand-rolled proration math.
19- [ ] Seats are modeled as a per-seat item quantity that updates on membership changes.
20- [ ] Dunning relies on Smart Retries plus reactions to `invoice.payment_failed` and `invoice.paid`.
21- [ ] No prices are stored locally; code references Stripe price IDs.
22- [ ] A nightly reconciliation job heals missed webhooks for subscriptions and entitlements.

Why this pattern

Usage-based subscription billing silently loses meter events, grants the wrong entitlements, and mis-charges on plan changes when webhooks and metering are handled ad hoc.

Built for SaaS and AI product teams running subscription plus usage-based billing on Stripe..

Keeps your assistant from:

  • Dropping usage because meter events are sent without idempotency or outside the accepted timestamp window
  • Granting or revoking the wrong plan access because entitlements are derived from redirect callbacks instead of webhooks
  • Double-applying webhook side effects or mis-charging customers on proration during plan upgrades and downgrades
License
Apache-2.0
Version
1.0.0
Updated
2026-06-09
View source