Move Recurring Interval outside the Product Price #4965
Replies: 2 comments 1 reply
-
Great write-up as always @frankie567 👏🏼 Fully supportive of this model for the future. Just want to fully flush out how we would roll this out without breaking existing integrations / data models - let's discuss 1:1 to figure it out. Minor thought: I think we could introduce this as if product.recurring: ... # Show Subscribe vs. Pay or whatever |
Beta Was this translation helpful? Give feedback.
-
Follow-up. @frankie567 and I chatted today and we're going with this approach, but with the following modification for backward compatability:
This only adds a little bit of overhead in the short-term, but guarantees we don't break any data models for integrations, i.e customers relying/checking a certain product ID to determine X credits to grant or equivilant. Since a migration would create at least 1 new ID for the given product (monthly vs. yearly) even though the API/Webhook payload would be the same. |
Beta Was this translation helpful? Give feedback.
-
This supersedes #4838
In our current efforts to support Usage-Based Billing, we'll need to introduce changes to how Prices are defined on a Product. In particular, we'll need to change the way Recurring Interval is handled.
Current state
Currently, we've six types of price:
On Recurring prices, we add the
recurring_interval
property which defines the interval of a cycle (monthly or yearly currently).A Product can either contain one or two Recurring Prices or one One-time Price. A Product is then considered as "recurring" (i.e. produces subscriptions) if it has at least one Recurring Prices.
Limitations
We can see this approach brings a bit of complexity, as it leads to have lot of different Price types just because of that recurring option. Besides, the recurring nature of a Product has to be determined by the Prices it contains.
The other challenge it poses is that we can't have multiple type of prices on a single Product. In particular, we would be highly interested to have, besides a fixed price for example, one or several usage-based prices.
Proposal
What we propose is to move the
recurring_interval
to the Product itself, meaning the recurring nature is determined by the Product and not by the Price anymore. Basically, this attribute would have three possible values:None
: a one-time purchase productmonthly
: a monthly recurring productyearly
: a yearly recurring productThus, we would come back to only three types of price:
In this first iteration, we would only allow to have one active price per Product. But the next goal will be to allow several ones, so we can support complex billing schemes.
Limitations
The main limitation is that users will no longer be able to have a single product with both a monthly and yearly pricing. This is a choice we're willing to undertake. If you need both, you can create another product with a yearly pricing, on which you'll probably want to add other benefits or have a slightly different pricing on usage-based for example. The drawback is around name/description/medias, but we can add tools to manage that easily on the UI side.
However, we will need to implement a mechanism allowing to switch them at Checkout. Basically, instead of passing a single
product_id
, we'll allow to pass several ones, i.e.products
. Then, the Checkout UI should show a selector on the left allowing the customer to switch between products. This new approach allows for a kind of "variants" feature.This mechanism should also be supported by Checkout Links.
Migration challenges
The main migration challenge comes from the Product that have both a monthly and yearly price. For them, we'll need to duplicate the Product, with the same properties/benefits and set the other interval on them. We'll also add a "Monthly" and "Yearly" suffix to their name.
For orders/subscriptions that were tied to that Product/Price, rewire them correctly to the duplicated one.
For Checkout Links tied to this Product, update them so they generate a session with both of those products, so the switching behaviour is maintained.
Backward-compatibility challenges
Currently, we can create a Checkout Session / Checkout Links by setting either a
product_id
or aproduct_price_id
. With this new approach, I propose we do the following:products
.product_id
. Still support it a first (i.e. just create a session with that single product), but recommend to migrate toproducts
product_price_id
. Still support it at first (i.e. translate to a single product), but recommend to migrate toproducts
Feedback and requests
Have some feedback or specific requests regarding this proposal? Feel free to share it with us 👇
Beta Was this translation helpful? Give feedback.
All reactions