Hi guys. Here is the way I have gone about this (bit of a hack I think) and not sure if it’s anywhere near best practice or not but is quite flexible. I am approaching this with a numerical system where I give each plan a number.
I then have conditions that show / hide, redirect, change app behaviour etc based on these values.
The main reason I have done this is to allow me flexibility to insert different plans / features in the future (for example a hypothetical future plan could be a BasicPlus plan that equals 30). Although I’d still need to tweek my conditional statements, it allows great flexibility in the conditions. For example, if a feature is available to plans above Basic (20), I can set the condition to > 20 and that captures all plans above the basic plan.
The other way I am looking to extend this is to have two data types called ‘Plan’ and ‘Plan_Feature’.
‘Plan’ would be general meta info on the plan (including numerical value, price, description etc). The plan would be tagged to the user.
The ‘Plan_Feature’ would contain the plan / feature combinations (one row per feature) and would follow the same numerical system and use binary values to switch things on and off.
This extension is theory at this stage and it would be great to hear any other thoughts on the best way to go about this.
One thing is for sure, I wish I had started thinking about the pricing / feature structure earlier and incorporated this into the base design. It has been pretty tough going back and changing all this stuff later to incorporate it.
I don’t know the best structure for all of this, but I think that it’d probably make more sense for you to abstact your approach 1 more level. In other words…
Rather than coding your app to show/hide elements for each plan that you offer (or offered in the past and still have someone using) you may want to structure it so that each plan has a list of features that are stored in the database. Then, each of the elements in your app would be shown/hidden based on whether a user has a plan that has that feature.
This way, you’re able to create a new plan and store what features it has in the database, and have your app work for that new plan without needing to change any of the logic. This will be really helpful as you create new plans and want to test different versions while continuing to support older plans, etc.
I’m not really sure what the right storage in the database should look like. That’s the primary reason why I asked this question in the first place. Here’s what I do know:
Binary flags seems like an easy way to set it up, but they leave no room for extendibility.
Additionally, I can imagine several use cases that may be worth designing for simultaneously – 1) feature flags for different plan prices, 2) feature flags to split test new features and their impact on KPIs, 3) feature flags to enable you to release updates while 1 or 2 features are still a work-in-progress.
So, I’ll probably look to set something up that keeps things simple while also giving me the longer-term option of addressing each of these core use cases.
Ok. So this is how I am approaching this now. Still a work in progress but is looking quite feasible.
Have a data type called ‘Plan’ and create a field for each feature.
Instead of a binary switch for each field, make each field a number
You need to decide on a field by field basis whether the field value is implicit or explicit.
Implicit would be something like Free = 0, Basic = 20, Advanced = 40 etc). Explicit would be something like ‘Members’ = 5 (meaning 5 members is the threshold for that plan).
Numerical fields will support implicit and explicit values. Just remember to make use of the notes in your data schema to keep track of this.
So to give you an example from my app and how this is coming together.
In my app, users create groups. In the free plan a user can have 1 private group (a group allows the user to store a collection of things).
Private groups are restricted to the group owner - no additional members can be added to that group.
In the basic plan, the user can have 1 premium group and 5 private groups.
A premium group on the basic plan allows the group owner to add up to 3 additional members to the group (so number of premium members would be 4).
You can see in the excel table how these values can be mapped to the plans.
Where fields are explicit and are always threshold values, you can set extreme upper limits for your top plan to support ‘unlimited’:
Here is a view of the data type to support this example.
Note: This could also be extended to include feature flags.
I’ve also created a Plan Membership data type that maps the user to the plan. This table allows you to activate and deactivate the plan membership, set discount rates etc. Could be quite flexible but I’m yet to really test this.
Here is an example of an expression implementing these controls.
I have added counter fields to the user that increment based on different actions. So here I am checking if the Premium Group Counter is <= the plans Premium Group value and setting a visibility control.
Haven’t yet decided where the most appropriate location is to store the counter fields, but at the moment, the user seems like the logical location.
This is where I am up to now. I’ll keep sharing as I progress.