Files
member-console/design/documents/reference-plan-enrollment-modeling.md
T
cgalo5758 bfe9cee0fe Consolidate design docs into documents directory
- Remove per-module projection files (README, architecture, companion,
  interfaces, model) under design/<module>/
- Add design/documents/ with numbered design docs, references, policies,
  and manifest
- Update design/README.md to describe the directory as a mirror of
  membcons-db's normative surfaces
- Record Decisions 140-141 in companion and glossary; update
  data-model.md schema organization
2026-08-21 00:55:42 -05:00

41 KiB
Raw Blame History

Plan enrollment modeling in multi-tenant SaaS: a comparative research synthesis

The question of how a SaaS platform authoritatively records "what plan is a tenant on" admits no consensus answer. Across nine major billing platforms — commercial and open-source — this synthesis identifies three fundamentally distinct representational strategies, each embedding different assumptions about the ontological status of a "plan." The deeper finding is structural: billing platforms universally decline to enforce tier exclusivity, treating it as application-layer concern; scheduled future changes lack a shared abstraction; and the very concept of a "plan" is under active decomposition, with usage-based systems dissolving it into rate cards and contracts. What follows is a systematic mapping of the solution space across six research dimensions, surfacing patterns, tradeoffs, and the unresolved tensions that practitioners still navigate without authoritative guidance.


§1. The ontology of plan state: three representational paradigms

The first and most fundamental architectural decision is how the billing system answers the query "what plan is tenant X on right now?" Investigation of Stripe, Chargebee, Recurly, Zuora, Orb, Lago, Kill Bill, and Paddle reveals three distinct paradigms, each with different implications for downstream entitlement systems, analytics, and operational complexity.

Paradigm A — Explicit plan reference. In Chargebee, Recurly, Lago, Orb, and Kill Bill, the Subscription object carries a direct pointer to a Plan entity. Recurly's subscription.plan returns the Plan object with its code, name, and pricing. Lago's API is literally named "Assign a plan to a customer," with plan_code as a first-class field on the Subscription, 1 2 supplemented by previous_plan_code and next_plan_code for transition tracking. 3 Kill Bill goes further, carrying planName, productName, productCategory, and phaseType directly on its Subscription entity, 4 with a formal separation between entitlement state and billing state. 5 Chargebee occupies a quasi-explicit position: every subscription must contain exactly one item of item_type: "plan", enforced as a structural constraint, 6 though the plan identity is extracted from the subscription's item list rather than a top-level field. 7 8 This paradigm optimizes for query simplicity and semantic clarity — "what plan is this tenant on?" reduces to a single field lookup. It sacrifices composability: multi-product subscriptions, mix-and-match pricing, and add-on-heavy models require escape hatches (add-on items, plan overrides, multiple subscriptions per customer).

Paradigm B — Derivation from subscription items. Stripe and Paddle model the Subscription as a container of line items (SubscriptionItems), each referencing a Price that references a Product. There is no first-class plan_id field. The "current plan" is whatever business meaning the application assigns to the combination of attached items. Stripe explicitly states that subscription items "allow you to create customer subscriptions with more than one plan." For a simple single-tier SaaS, developers typically examine subscription.items.data[0].price, but this is a convention, not a guarantee. This paradigm optimizes for maximum flexibility — any combination of products and prices can coexist on one subscription, enabling composable offerings without catalog restructuring. The cost is that practitioners consistently report needing a local billings table, synchronized via webhooks, to answer plan-identity questions without real-time API calls. 9 The mapping from "set of prices" to "plan identity" becomes application-owned state, introducing a synchronization boundary and a source of potential inconsistency.

Paradigm C — Hierarchical template instantiation. Zuora's model introduces a product catalog layer (Product → ProductRatePlan → ProductRatePlanCharge) from which subscriptions instantiate RatePlans. 10 11 A single subscription can contain multiple RatePlans from different Products, and each RatePlanCharge is segmented by effective dates when amendments occur. 12 "What plan is the tenant on?" requires navigating Subscription → RatePlan(s) → ProductRatePlan, and the answer is inherently multi-valued. This paradigm optimizes for enterprise-grade complexity — multi-product subscriptions, versioned amendments with full audit trails, and clean separation of catalog templates from instance data. The cost is the steepest learning curve of any platform studied, with query complexity compounded by temporal charge segmentation.

A critical cross-cutting finding emerges from this analysis: most billing platforms do not include a first-class entitlement system. Only Kill Bill architecturally separates entitlement from billing via its blocking_states table and dual entitlement/billing timelines. 13 Lago has recently added entitlements as a distinct feature. 14 15 Chargebee offers a separate entitlements module. 16 The practitioner consensus, articulated most thoroughly by Garrett Dimon's data modeling analysis for Flipper Cloud, is that plan identity, billing state, and entitlement state should be three loosely coupled concerns 17 — yet the dominant billing platforms conflate at least two of these.


§2. Tier exclusivity lives nowhere in the platform layer

Perhaps the most striking finding across all platforms investigated is the complete absence of database-level enforcement of plan-tier exclusivity. No commercial billing platform — Stripe, Chargebee, Recurly, Zuora, Paddle — uses unique constraints, partial indexes, or exclusion constraints to prevent a customer from holding two conflicting plans simultaneously. Kill Bill enforces "at most one BASE subscription per bundle" in Java application code, not via SQL constraints. 13 Lago allows multiple subscriptions per customer including on the same plan, with external_id uniqueness as the only integration-level hook.18

The architectural reason is consistent: what constitutes "conflicting" plans is business-specific logic that billing platforms cannot generalize. Multi-subscription support is a legitimate business need (multiple products, multiple billing entities), and database constraints would be too rigid. The exclusivity question reduces to: "can a customer have multiple subscriptions?" The answer is universally yes.

This means SaaS developers must construct their own enforcement layer. A practitioner-documented PostgreSQL pattern uses a partial unique index:

CREATE UNIQUE INDEX idx_one_active_sub_per_customer
ON subscriptions (customer_id)
WHERE status = 'active';

Or, for temporal exclusion, PostgreSQL's GiST-backed exclusion constraint:

EXCLUDE USING gist (
  customer_id WITH =,
  tstzrange(starts_at, ends_at) WITH &&
) WHERE (status = 'active');

No commercial billing platform exposes either mechanism to users.

How "swap" operations avoid momentary violation

The plan-change operation reveals further divergence. Five of seven platforms studied use in-place mutation: Stripe replaces the Price on a SubscriptionItem via Subscription.modify(); 19 20 Recurly creates a first-class SubscriptionChange object that is applied to mutate the subscription; 21 22 Chargebee updates the plan item directly; 23 Paddle requires the complete desired state of items in every PATCH request; 24 and Kill Bill performs changePlan() on the Subscription entity. 13 25 In all cases, the subscription ID is preserved and the swap is atomic from the API consumer's perspective — there is no moment where two plans coexist on the same subscription item.

Lago is the notable exception, using a genuine terminate-and-create pattern for upgrades: the old subscription is terminated, a new subscription is created, 26 and external_id is threaded through to maintain logical continuity. Two webhooks fire (subscription.terminated with next_plan_code, then subscription.started with previous_plan_code), creating a brief logical window where webhook consumers must handle two events atomically. 3 27 Zuora occupies a middle position: its legacy amendment model requires paired Remove + Add operations on rate plans within a single API call, 28 and its modern Orders framework orchestrates multiple order actions in one transaction.

Payment failure during upgrade represents a critical edge case with divergent solutions. Stripe offers pending_update semantics: with payment_behavior: 'pending_if_incomplete', the subscription retains its original plan and stores the pending changes in subscription.pending_update until the invoice is paid. 29 Paddle defaults to on_payment_failure: 'prevent_change' 30 — the strongest default guard found, blocking the subscription change entirely if the charge fails. 24 Chargebee applies changes regardless of payment outcome, relying on its dunning process. Kill Bill's overdue module provides configurable blocking states. 13 31 No consensus exists on whether a failed-payment upgrade should silently revert, block, or proceed with dunning.


§3. Per-product plan state in multi-service platforms

When a platform offers several independent products each with its own tier ladder, three architectural patterns emerge for tracking per-service plan state, each embedding different assumptions about product independence and billing cohesion.

Pattern 1 — Separate subscriptions per product. Atlassian, Google Workspace, and Chargebee (via Item Families) each give every product its own subscription record. Atlassian's data hierarchy runs Organization → Site(s) → Product Subscriptions, where each product (Jira Software, Confluence, JSM, Bitbucket) carries an independent plan tier (Free, Standard, Premium, Enterprise). 32 Google Workspace models each product (Workspace Business Standard, Vault, Drive Storage, Chrome Enterprise) as a separate SKU with its own subscription in the Reseller API: customerId + skuId + plan + seats + status. 33 Chargebee scopes plans, addons, and charges to Item Families — each subscription has exactly one plan from one family, 34 and multi-product customers require separate subscriptions per family.35

This pattern optimizes for lifecycle independence: each product can trial, activate, pause, and cancel on its own schedule. Cross-product billing consolidation requires explicit co-terming (Atlassian groups subscriptions into a billing profile; Google requires unassign-then-assign for edition changes). 32 The tradeoff is invoice proliferation and complex cross-product discounting.

Pattern 2 — Composite subscription with multiple line items. Stripe (via SubscriptionItems) and Zuora (via multiple RatePlans per Subscription) fold all products into one subscription. A Stripe subscription can carry up to 20 items, each referencing a different Product/Price. 36 Zuora's single subscription can contain RatePlans from different Products in the catalog. This pattern optimizes for billing cohesion — single invoice, unified billing cycle, natural cross-product discounting. The tradeoff is coupled lifecycles: canceling one product requires modifying the subscription rather than simply terminating it, and mixed billing intervals create complications (Paddle prohibits them entirely; 37 Stripe's newer flexible billing mode partially addresses them).38

Pattern 3 — Composite license with decomposable service plans. Microsoft 365 represents the most granular approach. Each license SKU (e.g., ENTERPRISEPREMIUM / E5) contains an array of individually toggleable service plans86 service plans in E5 alone, across a total landscape of 555 SKUs and 714 service plans as of 2024. 39 The Graph API exposes user.licenseDetails[].servicePlans[], where each service plan has its own servicePlanId, servicePlanName, and provisioningStatus. 40 41 Administrators can disable individual service plans within a license via the disabledPlans array. 42 This pattern optimizes for administrative granularity within bundled offerings but introduces enormous complexity: conflict resolution across overlapping SKUs becomes a combinatorial problem, 43 and the service plan matrix must be maintained as a managed artifact.

The query "what plan is tenant X on for Product Y?" resolves differently in each pattern: a subscription filter in Pattern 1, an item-product join in Pattern 2, and a service plan decomposition in Pattern 3. No pattern dominates — the choice is driven by the degree of product independence and billing consolidation a business requires.


§4. Bundle-component relationships and the exclusivity enforcement gap

Bundle modeling reveals the deepest tension in subscription data architecture: the need to represent a composite commercial offering (a bundle SKU covering multiple products) while maintaining the integrity constraints that prevent a customer from simultaneously holding both the bundle and its constituent standalone tiers.

Microsoft 365 is the only platform studied that enforces bundle-vs-standalone exclusivity at the platform level. When an administrator attempts to assign both Office 365 E1 and E3 to the same user, the operation fails 43 with a MutuallyExclusiveViolation error 43 44 — enforced not at the SKU level but at the service plan level, checking whether any service plans in the new SKU conflict with service plans already assigned from other SKUs. This is the canonical approach for complex multi-product bundles but requires maintaining a conflict matrix across hundreds of service plans. Google Workspace enforces edition-level mutual exclusivity at the API level (must unassign one before assigning another) but does not decompose editions into sub-service-plans.45

Adobe Creative Cloud illustrates the opposite extreme: no automated mutual exclusivity enforcement. A user can accidentally hold both an All Apps license and a Single App license for an app already included in All Apps. Adobe's guidance is manual audit: "Ensure each person only has the licenses they need." 46 Multiple licenses are consumed if the same user is assigned to multiple product profiles.

Among billing platforms, Zuora has introduced explicit bundle support (Early Availability): a Bundle Product references multiple standalone Products, and a Bundle Plan inherits all charges from selected component plans 47 48 with per-charge customization (keep, modify, merge, or remove). However, mutual exclusivity between bundles and standalone subscriptions is not enforced — application logic must prevent overlap. Chargebee models bundles as a special plan type where all entitlements from included items are automatically inherited, but again, "no strict rules — your application's logic may impose certain rules." 49 Stripe has no bundle concept at all; bundles must be modeled either as a single opaque "bundle Product" (losing component visibility) or as multiple SubscriptionItems (losing bundle identity). 50 Kill Bill provides the most extensible mechanism: entitlement plugins can intercept and block conflicting subscriptions, but the enforcement logic must be custom-written.51

The bundle-to-standalone transition is universally manual. No billing platform automates the sequence of cancel-standalone → create-bundle → prorate → update-entitlements. This is always orchestrated by application logic. The reverse (unbundle to standalone) is even less supported — Zuora's V1 bundle support explicitly prohibits post-sale unbundling.52

The most robust architectural response to this challenge is entitlement separation: decoupling what was purchased (billing/subscription records) from what can be accessed (entitlement/feature state). 53 54 A bundle's billing record can be opaque while the entitlement layer transparently maps to granular per-feature access. Kill Bill's built-in entitlement service, 55 Chargebee's entitlements module, and the practitioner pattern of system-level entitlement tiers independent of pricing versions 17 all point toward this decoupling as the emerging consensus 17 — yet no billing platform fully unifies bundle modeling with entitlement enforcement.


§5. Lifecycle states and the representation of future change

Enrollment lifecycle modeling reveals a continuum from minimal state machines (4 states) to richly temporal, event-sourced architectures. More importantly, platforms diverge sharply on how they represent scheduled future changes — a downgrade effective at next renewal, a phase transition, or a contract amendment.

The lifecycle state spectrum

Stripe defines 8 subscription statuses (incomplete, incomplete_expired, trialing, active, past_due, unpaid, canceled, paused), 56 which practitioners categorize into three meta-states: ALIVE (active, trialing), SUSPENDED (incomplete, past_due, unpaid, paused), and DEAD (canceled, incomplete_expired). 57 Zuora adds versioned subscription states (Draft, Pending, Active, Suspended, Cancelled) with three independent billing trigger dates (Contract Effective, Service Activation, Customer Acceptance). 58 Kill Bill manages 5 explicit states (PENDING, ACTIVE, BLOCKED, CANCELLED, EXPIRED) but supplements these with a catalog-driven phase system where plans contain ordered PlanPhases (TRIALDISCOUNTFIXEDTERMEVERGREEN) that transition automatically based on the catalog definition and the clock. 59 Lago has the most parsimonious model at 4 states (pending, active, terminated, canceled), but its pending state carries distinctive semantics: it represents a downgraded subscription awaiting activation at the end of the current billing period.27

Five approaches to scheduled future changes

The representation of "this tenant will be on Plan X starting next month" admits five distinct architectural solutions:

Separate schedule entity (Stripe). Stripe's SubscriptionSchedule is a separate API object wrapping an underlying Subscription, defining ordered phases — each with its own items, quantities, coupons, and proration behavior. 56 Phase transitions happen automatically. 60 The schedule has its own lifecycle (not_started, active, completed, released, canceled) independent of the subscription's status. 61 This is the most flexible model for complex multi-phase plans but introduces a coordination challenge: modifying a subscription directly while a schedule is attached can cause the schedule to overwrite changes on next phase transition.60

Flag-based embedding (Chargebee). Chargebee stores pending changes as an implicit overlay on the subscription, exposed via a has_scheduled_changes boolean. 8 A separate "Retrieve with scheduled changes" API returns the subscription's future state. This approach has a documented fragility: updating any subscription field (even unrelated attributes like quantity) while scheduled changes exist silently removes the scheduled changes. 62 Only one scheduled change per subscription is supported.63

Explicit change resource (Recurly). Recurly's SubscriptionChange is a first-class object attached to a subscription, with three timeframes (now, bill_date, term_end). 22 Only one pending change is retained — submitting a new change nullifies the previous one. 64 65 This cleanly separates "what the subscription is now" from "what it will become" but limits flexibility to a single pending transition.

Versioned amendments (Zuora). Each Zuora amendment creates a new version of the subscription, with all previous versions retained and navigable. 28 66 Amendments have their own lifecycle (DraftPendingComplete) and support future-dated effective dates. 67 68 This is the closest to a true bi-temporal model, distinguishing transaction time (when the amendment was created) from valid time (when it takes effect). The subscription detail page shows the complete version history. 66 69 The cost is complexity: a limit of 1,000 amendments per subscription is documented, with a performance recommendation of ≤100.28

Dual subscription records (Lago). When a downgrade is requested, Lago creates a new subscription record with pending status alongside the existing active subscription. Both records coexist in the database. When the billing period ends, the active subscription terminates and the pending one activates. 27 This makes the "superseded enrollment" concept explicit in the data model — queryable by status filter — but requires managing two subscription records simultaneously and handling the webhook sequence atomically.

Kill Bill and Orb represent additional approaches: Kill Bill's event-sourced architecture stores all changes as immutable SubscriptionEvents with effective_date fields, enabling time-travel queries; 70 Orb manages subscriptions as collections of price intervals where individual prices can be independently added, removed, or scheduled without affecting other prices, avoiding the "re-specify everything" problem of phase-based systems.71

Interaction with proration and invoicing

Scheduled changes interact differently with billing across platforms. Stripe's pending downgrades (in a schedule phase) continue billing at the current phase's rate until transition. Chargebee's scheduled changes do not affect current billing, but the proration and unbilled charges APIs do not account for them. Recurly's "at renewal" changes apply cleanly at the next billing date with no proration. 64 72 Zuora's amendment effective dates determine when billing changes take effect, with prorated charges appearing on the next invoice for mid-period amendments. 28 73 The general principle is that a scheduled future change does not affect current-period billing, but the mechanisms for computing transition-point proration vary significantly.


§6. When there is no plan: the rate card dissolution

The final research dimension examines the most architecturally provocative case: tenants on purely metered or à la carte usage who have no "plan" in the traditional tier-ladder sense. The central finding is that a structural entity linking customer to pricing is almost universally required, but its semantics are actively shifting from "plan" (a bundle of features and a price) to "rate card" (a named collection of pricing rules).

The $0 plan workaround is the dominant pattern among platforms that require a Plan object. Lago, Kill Bill, and Stripe all permit creating a Plan with zero subscription fee and only usage-based charges. 1 The Plan still exists as a structural entity — it defines billing cadence, currency, and invoice grouping — but carries no fixed cost and implies no tier. Orb similarly requires a Plan, but Orb's documentation explicitly frames plans as "list pricing" containers: 74 "if you see multiple tiers of your offering such as Pro, Starter, or Gold, each of these would correspond to a plan in Orb." 75 For purely metered customers, the Plan degenerates into a rate card with no tier semantics.

Metronome represents the most radical departure from the plan paradigm. Acquired by Stripe in 2024, Metronome replaces "plans" and "subscriptions" with Rate Cards and Contracts. 76 A Rate Card is a centralized, temporal, append-only pricing definition — modular (update a rate without rewriting full config), centralized (one change reflects everywhere), temporal (each pricing element has effective date ranges), and append-only (full audit trail). 77 A Contract ties a Customer to a Rate Card with overrides, commits, and credits. Metronome explicitly articulates why plan-based models fail for usage-based pricing: plans bundle pricing, packaging, and commercial model into a single object, causing every price change to require plan version creation and customer migration. Rate cards decouple these concerns. 77 The influence of this model is visible in Stripe's new v2 Pricing Plans (private preview), which decompose into Rate Card (usage-based), License Fee (recurring), and Service Action (credit grants) 78 — a direct evolution toward the rate card architecture.

Zuora's Dynamic Usage Charges represent the only path to genuinely subscription-less billing in a traditional billing platform. Usage charges attach directly to accounts without creating subscriptions or orders, referencing a ProductRatePlanCharge from the catalog for pricing. Price changes in the catalog automatically reflect in all customer bills. 79 The limitation is significant: dynamic usage charges cannot access subscription-level billing attributes (bill-to contact, payment terms, invoice template).79

Cloud providers and API-first companies like AWS and Twilio operate with implicitly planless architectures. AWS has no per-service plan concept — each of 200+ services meters independently, and the billing system aggregates into a consolidated monthly invoice. The "rate card" is the published pricing page. Twilio bills per-API-call with no required subscription. Snowflake and Datadog occupy a hybrid position: they maintain tiers (Standard, Enterprise) that determine both the per-unit rate and feature access, making the plan simultaneously a rate card and a feature gate.

The emerging consensus is that even the most usage-focused platforms need some structural entity linking customer to pricing. 80 The unresolved tension is whether this entity should also carry feature-gating semantics (entitlements) or whether pricing and entitlements should be fully decoupled. Orb explicitly notes that "none of the usage-based billing providers on the market allow you to capture this concept of features enabled or disabled at a plan level" 81 — the Plan in Orb is purely a pricing construct. OpenMeter takes the opposite position, embedding both Entitlements (usage limits, boolean access) and Rate Cards within its Plan object. The rate card dissolution is incomplete: the industry has not yet converged on whether a "plan" should be purely financial or should retain packaging semantics.82


Conclusion: five structural tensions that remain unresolved

This synthesis reveals a solution space that is broader and less settled than it may appear from any single platform's documentation. Five tensions persist across the landscape:

First, the locus of plan identity. The choice between explicit plan reference and derivation from subscription items is not merely an API design preference — it determines whether plan identity is a platform-managed truth or an application-managed interpretation. Platforms that make plan identity explicit (Recurly, Lago, Orb) optimize for operational simplicity but constrain composability. Platforms that leave it derived (Stripe, Paddle) maximize flexibility but externalize a critical piece of domain state.

Second, the enforcement vacuum. No billing platform enforces tier exclusivity at the database level. This is a deliberate architectural choice — business rules about what constitutes "conflicting" plans are too domain-specific to generalize. But it means every SaaS developer independently re-implements exclusivity logic, often imperfectly, in their application layer. Microsoft 365's service-plan-level conflict detection is the only platform-enforced exclusivity mechanism found, 43 and it is specific to Microsoft's own licensing model, not exposed as a general-purpose billing primitive.

Third, the atomicity of plan transitions. In-place mutation (Stripe, Chargebee, Recurly, Paddle, Kill Bill) preserves subscription identity and avoids service gaps but makes historical state implicit. Terminate-and-create (Lago) makes history explicit but introduces a two-event coordination problem. 3 Versioned amendments (Zuora) provide the strongest audit trail 69 but at the highest complexity cost. 69 No approach cleanly resolves the payment-failure-during-upgrade case — Stripe's pending_update 29 and Paddle's prevent_change are the most robust guards, 24 but neither is a universal standard.

Fourth, the temporal representation of future state. Scheduled changes are modeled as 83 separate schedule entities (Stripe), embedded flags (Chargebee), explicit change resources (Recurly), versioned amendments (Zuora), dual subscription records (Lago), 84 price interval mutations (Orb), 71 or event-sourced timelines (Kill Bill). The lack of a shared abstraction means that every integration must understand the idiosyncratic temporality of its chosen platform. Bi-temporal modeling — distinguishing when a change was recorded from when it takes effect — remains the province of Zuora and Kill Bill, with most platforms offering only a single temporal axis.

Fifth, the dissolving plan. The concept of a "plan" is under active decomposition. Usage-based billing is pushing the plan toward a pure rate card — a pricing container with no tier or feature semantics. 82 85 Metronome's rate card architecture 77 and Stripe's emerging v2 model suggest a future where "plan," "rate card," "contract," and "entitlement tier" are fully independent concepts. But this decomposition is incomplete: most platforms still require a Plan object even for purely metered billing, and the question of whether pricing and entitlements should share a structural anchor or be fully decoupled remains open. The industry is mid-migration between two ontologies — the plan-as-bundle and the plan-as-rate-card — and practitioners must navigate both simultaneously.


Sources


  1. Lago — Lago Blog | 6 steps to build a usage-based billing system ↩︎

  2. Lago — The subscription object - Lago ↩︎

  3. Lago ↩︎

  4. Killbill — Quick Start with the Kill Bill API ↩︎

  5. Killbill ↩︎

  6. Chargebee — Plans - Chargebee Docs ↩︎

  7. Chargebee — Product Catalog - Chargebee Docs ↩︎

  8. Chargebee — Subscriptions | Chargebee API documentation ↩︎

  9. Indie Hackers — Suggested database architecture for my first SaaS with Stripe? - Indie Hackers ↩︎

  10. Zuora — Product catalog concepts | Zuora Product Documentation ↩︎

  11. Zuora — Rate Plan Charge Data Source - Zuora ↩︎

  12. Zuora — Product catalog concepts - Zuora ↩︎

  13. Killbill ↩︎

  14. Lago — Welcome to Lago - Lago ↩︎

  15. GitHub — GitHub - getlago/lago: Open Source Metering and Usage Based Billing API Consumption tracking, Subscription management, Pricing iterations, Payment orchestration & Revenue analytics ↩︎

  16. Chargebee — Subscription Management Software for Seamless Scalability | Chargebee ↩︎

  17. Garrettdimon — Data Modeling Entitlements and Pricing for SaaS Applications ↩︎

  18. Chargebee — Plans - Chargebee Docs ↩︎

  19. Stripe — Change the price of existing subscriptions | Stripe Documentation ↩︎

  20. Stripe — The Subscription Item object | Stripe API Reference ↩︎

  21. Recurly — Subscription management methods | Recurly Developer Hub ↩︎

  22. Recurly — Subscription management guide ↩︎

  23. Chargebee Docs — Can I change the plan of an existing subscription on behalf ... ↩︎

  24. Paddle Developer ↩︎

  25. Killbill — Plan Alignments ↩︎

  26. Getlago — Plan model - Lago ↩︎

  27. Lago — Upgrades and downgrades - Lago ↩︎

  28. Zuora — Amend subscriptions - Zuora ↩︎

  29. Stripe ↩︎

  30. Paddle Developer — Change billing dates - Paddle Developer ↩︎

  31. Killbill — What Is Kill Bill? ↩︎

  32. SPK and Associates — Demystifying Atlassian Cloud Licensing - SPK and Associates ↩︎

  33. Google — Reseller API overview | Admin console | Google for Developers ↩︎

  34. Chargebee — Items | Chargebee API documentation ↩︎

  35. Chargebee — Item families | Chargebee API documentation ↩︎

  36. Stripe ↩︎

  37. Paddle Developer — Add or remove items from a subscription - Paddle Developer ↩︎

  38. Stripe — Mixed interval subscriptions | Stripe Documentation ↩︎

  39. Office 365 IT Pros — New Cloud Licensing Graph API Released in Beta ↩︎

  40. Microsoft Learn — subscribedSku resource type - Microsoft Graph v1.0 | Microsoft Learn ↩︎

  41. Microsoft Learn — List licenseDetails - Microsoft Graph v1.0 | Microsoft Learn ↩︎

  42. Practical 365 ↩︎

  43. Microsoft Learn — Product names and service plan identifiers for licensing - Microsoft Entra ID | Microsoft Learn ↩︎

  44. Microsoft Learn — Resolve group license assignment problems - Microsoft Entra | Microsoft Learn ↩︎

  45. Google — Enterprise License Manager API Developer's Guide | Admin console | Google for Developers ↩︎

  46. Redress Compliance — Adobe Creative Cloud Enterprise Licensing & Optimization ↩︎

  47. Zuora — Add a new hard bundle | Zuora Product Documentation ↩︎

  48. Zuora — Bundles in Product Catalog | Zuora Product Documentation ↩︎

  49. Chargebee — Upselling Just Got Smarter and Simpler with Add ons - Chargebee ↩︎

  50. Stripe — Multiple plans and previews for subscriptions ↩︎

  51. Kill Bill ↩︎

  52. Zuora — Limitations and known behaviors | Zuora Product Documentation ↩︎

  53. SLASCONE — The Role of Licensing and Entitlements in SaaS and Multi-Tenant Apps ↩︎

  54. Killbill — Entitlement subsystem ↩︎

  55. Kill Bill ↩︎

  56. Stripe — The Subscription object | Stripe API Reference ↩︎

  57. Onur Solmaz blog — Stripe Subscription States | Onur Solmaz blog ↩︎

  58. Zuora ↩︎

  59. Kill Bill ↩︎

  60. Stripe — Subscription schedules | Stripe Documentation ↩︎

  61. Stripe — SubscriptionSchedule (stripe-java 32.0.0 API) ↩︎

  62. Chargebee — Scheduled subscription changes are removed if I update the subscription. : Chargebee Help Center ↩︎

  63. Chargebee — Can I change the plan of an existing subscription on behalf of the customer ? ↩︎

  64. Recurly — Subscription billing terms ↩︎

  65. Recurly — Change subscription ↩︎

  66. Zuora — Subscription Amendments - Zuora ↩︎

  67. Zuora — Amendment - Zuora ↩︎

  68. Zuora — Rate Plan Data Source - Zuora ↩︎

  69. Zuora — Amendments - Zuora ↩︎

  70. Killbill ↩︎

  71. Orb — Orb | A guide to evaluating a billing system, part 1 ↩︎

  72. Recurly — Subscription billing terms ↩︎

  73. Zuora — Use cases of mapping order actions or amendments - Zuora ↩︎

  74. Withorb — Custom pricing - Orb ↩︎

  75. Withorb — Core concepts | Orb API ↩︎

  76. Metronome — Metronome Docs - Metronome ↩︎

  77. Metronome — Rethinking Pricing Architecture: How the Centralized Rate Card Model Unlocks Pricing Agility | Metronome blog ↩︎

  78. Stripe — Implement advanced usage-based billing with pricing plans | Stripe Documentation ↩︎

  79. Zuora — Dynamic Usage Charges | Zuora Product Documentation ↩︎

  80. Lago — Lago Blog | What are feature entitlements and how do they work? ↩︎

  81. Knock — Implementing a usage-based billing system: integration deep dive (part 2) | Knock ↩︎

  82. GitHub — GitHub - LocAI1/billing-lago: Open Source Metering and Usage Based Billing API Consumption tracking, Subscription management, Pricing iterations, Payment orchestration & Revenue analytics ↩︎

  83. Paddle Developer — Subscriptions - Paddle Developer ↩︎

  84. Lago — The subscription object - Lago ↩︎

  85. Chargebee — Mastering Usage-Based Billing for Subscription Growth ↩︎