An engineer’s step-by-step guide to plan versioning

Versioning is a critical concept for engineers building pricing plans in SaaS. In this article, we're sharing everything we've learned about plan versioning and how you can enable it in your codebase.

An engineer’s step-by-step guide to plan versioning

It’s common for SaaS companies to change their pricing multiple times per year - adding or removing a feature, changing the packaging of a plan, updating the price, introducing a trial, … 

New requirements keep coming. 

Package versioning is crucial for developers working on pricing plans for SaaS companies. Creating separate versions for every change you make in a pricing plan will give you full flexibility in how you introduce changes, to who, and when. It will enable you to support grandfathering, segmentation, and even pricing experiments, the moment the business needs it. 

Talking with 87 engineering teams, we found plan versioning to be essential for every SaaS business, no matter the size. As part of our product, we’ve put a lot of effort into plan versioning and have learned a lot.

In this article, we’re going to share why you should start versioning your plans and how to do it.

3 reasons why you should version your plans, starting now

Changing something in your pricing usually has a big impact on your existing customers. So, naturally, you’ll want to have full control over the rollout - who is affected, to what extent, and when. We’ve summarized the three main use cases:

1. Keep legacy customers on their original plan (= grandfathering), without turning your codebase into spaghetti code

Most SaaS companies underprice when they first charge for their services. You start with something that’s built to the best of your knowledge, but then you realize your product value is much bigger and your buyers’ needs are much more diverse. 

Pricing changes are inevitable as a business grows. Yet, nobody wants to cause a riot in their existing customer base. Grandfathering allows legacy customers to continue on their original plan, while you introduce new pricing to new customers.

Now, things get complex. 

As you’re experimenting with different pricing over time, you’ll have different customers of different pricing schemes that you need to account for while migrating them. That means additional code that is required from you to support each version, code branching, and more and more complex code you’ll have to maintain over time. 

Grandfathering is the number 1 cause for SKU sprawl. We’ve worked with multiple companies frustrated about the mess inside their codebase. Don’t get there! Plan versioning can be your way out of this. 

2. Enable segmented pricing rollouts

Another layer of complexity. As your business grows, the way you roll out pricing changes needs to be different for different customers. These are a few examples:

  • Varying packaging or prices for specific geographies
  • Launching a new feature in beta for a smaller group of your customers
  • Sunsetting a feature and granting a grace period to a limited group of customers.
  • Giving customers from bigger organizations an exclusive promotion or extended access to certain features

There’s almost no end to the requirements the business may have - now and in future. Supporting plan versioning will allow you to segment rollouts. Or in other words, if you don’t version your plans, you won’t be able to support segmentation. 

3. Allow pricing experiments

Pricing experimentation allows your PM, founder, or growth manager to run multiple versions of your pricing to determine which one performs best. 

Versioning your packages from the get-go allows you to experiment with different packages for different customers and find the one that converts better. 

Without plan versioning, you can’t run experiments. The moment your business is ready to scale, this will become a massive pain point for your engineering team. 

“Ok, I got it. How do I version our plans?”

I the beginning, all your customers are on one version of each plan, which is naturally the “latest” version. Let’s say you want to change the price of your Growth plan from $79 to $99. 

Here’s how you can implement it:

  1. Add a flag that indicates when the current plan version is the latest.
  2. Add a latest boolean to your Growth plan that packages the set of features and the price the customer is paying.
  3. Add a version number to your plan entity and set this initial version to 0.
  4. Add a status of published to your plan.
  5. Clone the current plan version as a new plan in draft status. Set this new version to be 1. You can simply bump it by one from the initial version.
  6. Apply your changes. In this example, we change the price to $99.

Now comes the good part… The publishing process should be as follows:

  1. Publish your plan!!
  2. Mark the new plan version as “latest” and “published”.
  3. Mark the old plan version as “archived” and remove the latest boolean from it.
  4. Make sure that all your pricing tables, in-app and on the website, are pointing to the latest version of the plan.

Caveats for you to consider

📌 When determining whether the customer has access to a specific feature, your check needs to take the package version of the specific customer into consideration. Different versions might include different features.

📌 When a customer is being grandfathered

  • Ensure that for any update you’re using the values of the correct plan version.
  • if you’re supporting usage-based pricing, you’ll need to use the previous price when additional usage is reported.

📌 If you migrate all current customers to the new version, define when this migration is going to happen. Out of fairness to your customers, we recommend applying changes at the end of the current billing cycle. This will require you to build something to schedule those migration tasks (📣 Coming soon: Subsequent article on how we’ve built this in Stigg). Needless to say, changing pricing plans for existing customers will need to be transparently communicated, too.

📌 Bear in mind that a non-migrated customer can upgrade (or downgrade) to another tier anytime. You will need to decide if they are going to be subscribed to the new package price or the old one. Common practice we’ve seen is to give customers a grace period to upgrade to the old plan version price. After the grace period is over, customers who upgrade will be subscribed to the new plan version by default.

📌 Consider what you will display to customers in the in-app paywall. Their old plan or the new plan? If not clearly defined, in the best case scenario this will cause troubles for your CS team. More likely, this will cause you to lose self-service upgrades, because your legacy customers won’t understand the implications to their plan once they upgrade. We’re experiencing this first-hand as a user right now. 🥴

Enable plan versioning with minimal engineering resources

If you don’t have the time to build all of this right now, and still want to allow your business to support plan versioning, check out Stigg. We’ve built all of this and more, giving you an out-of-the-box, flexible pricing & packaging platform. 

You’ll only need to call provisionSubscription in order to create new subscriptions in the latest plan version. updateSubscription will automatically update the subscription using the current package version that the customer is on.

Here’s a simplified version of the snippet:

Link to code

Pricing in SaaS is complex. Our team of Ex-New Relic engineers and product managers has learned that the hard way when we had to support an entire pricing model redo. Existing billing providers are not built for common use cases in SaaS and companies are forced to do a lot of undifferentiated heavy lifting to be able to properly monetize what they’re building. 

Our APIs and software give you a first-class, fully flexible pricing & packaging infrastructure to build and maintain pricing models, with minimal engineering resources. Check it out - it’s free.