FlowFuse / flowfuse

Build bespoke, flexible, and resilient manufacturing low-code applications with FlowFuse and Node-RED
https://flowfuse.com
Other
265 stars 63 forks source link

Support for annual billing option #4318

Open knolleary opened 1 month ago

knolleary commented 1 month ago

Part of https://github.com/FlowFuse/customer/issues/233

We want to provide the option for a user to pay annually, rather than the existing monthly model. This issue is for the technical work needed to achieve that.

Current Model

Desired Model

The desired model described in the linked issue is to have a minimum cost for Team/Enterprise - and for annual billing to be available in order to apply a discounted rate.

We have two options for implementing that:

  1. Use the current model to add a stripe price/product to the Team/Enterprise tier teams. Then set the 'free' allocation of the available instance type to match what is included in that base price. This way the billing system won't do on-demand charging for the first X instances - only when they go above X. The problem with this approach is it doesn't allow the user to commit to more than the minimum number that the team price factors in. So whilst this may offer a quick solution, it doesn't get us closer to where we want to be.

  2. The better model is, when setting up billing, let the user pick the desired team type, then be shown a slider for how many instances they want included - with the minimum applied. When they checkout, we then add the appropriate number of instances items to the subscription. The billing system can then ensure the item count on the subscription does not go below the defined minimum.

Annual billing

Supporting annual billing option is fairly straight forward to do the basics:

  1. The current billing interval is determined by the stripe price. So the starting point is to create yearly price objects for each stripe product.
  2. The TeamType configuration (which holds tier-specific pricing for each instance type), needs extending to include the yearly price details (two fields to add: stripe price ID, and the price we show on the page) for the team.
  3. Add toggle on Upgrade Team page (where the user picks Team Tier), for monthly/yearly pricing.
  4. Add flag on api to indicate monthly/yearly billing choice

Problems to resolve

If a user subscribes with Annual billing for 5 instances, what happens when they create their 6th instance.

We need to resolve the desired behaviour for on-demand usage that exceeds their initial subscription.

knolleary commented 1 month ago

I've looked at how other services approach this to see if there's a model we can easily adopt.

With my mental model of Stripe subscriptions, this is a model I can relate to. Stripe doesn't let you have a single subscription with mixed billing cycles - so this looks like the account has separate annual and monthly subscriptions - with a chore of moving items from the monthly-sub to the annual-sub.

All of our billing code operates on the principle of a team having a single subscription. Having a model with two different subscriptions to manage will require a fair amount of work - both backend and frontend.

gstout52 commented 3 weeks ago

@knolleary To keep invoice changes to a minimum when a customer is in an ongoing annual plan, I propose that customers on Team and Enterprise (1) start a new annual subscription whenever they add instances and (2) buy instances in bundles of 5.

(1) is for simplicity and because it is compatible with our current implementation of Stripe. Michael informs me that this is how Salesforce handles mid-term contract upgrades. (2) will minimize the number of contract changes that are needed. If a customer isn't sure whether they want to buy 12 instances or 14 instances, we inform them that they'll actually be paying for 15, and the next bump up is to 20 instances. This will allow them to allocate their flows appropriately, provide the opportunity for upsells, and minimize the number of invoicing changes that have to be made during a 12 month period.

knolleary commented 1 week ago

@gstout52 what you are proposing means a team can have multiple subscriptions. That is a fundamental change to our billing system that has always worked on the basis that a team has a single subscription. It opens up a lot of edge cases to deal with - what happens if they fail to pay on one subscription but not another for example. I don't know if that can be achieved in the next 3 weeks with all of the other pieces we still need to do for the pricing changes.

knolleary commented 1 week ago

(1) start a new annual subscription whenever they add instances and (2) buy instances in bundles of 5.

The more I think about how this would work, the bigger the set of changes are.

Our current model is very simple; each time an instance is created/deleted, we validate the quantity of the corresponding stripe product matches what they have so they are charged for what they are using.

As discussed previously, I could see a path forward to have a minimum purchase when they create the team; have the $-amount of the team price be equivalent to X instances - where X is a fixed amount.

To support pre-purchasing bundles of instances is a significant change. We now need to track separately what they have purchased from what they are using. Plus all of the UX work around what happens if a user has paid for 5 instances and they want to create a 6th. In our current model, they just create the instance. But now we have to block that until they go via stripe to create a new subscription (entering in all their billing details again) to increase their allowed instance count.