This article is a technical deep dive into the role of entitlements in SaaS monetization, written by our Co-founder and CTO Anton Zagrebelny.
A very special thanks for the first-hand insights and feedback to Utkarsh Sengar, Director of Engineering at Webflow, Barak Peleg, VP Technology & Architecture at AI21Labs, Greg Unrein, former CTO at Hasura and GVP Engineering at New Relic, Jonathan Pearlin, Staff Software Engineer at Airbyte, Guy Smoilovsky, Co-founder and CTO at DagsHub, and Itai Katz, Principal Software Engineer at Swimm. 💙
How many times did you change something in your pricing?
If you’ve been around SaaS for a while, you know how dynamic this landscape is, forcing companies to continuously update their pricing and packaging to stay competitive.
Yet, every change entails a corresponding change in the codebase to accommodate the new packaging behavior, inherently becoming more complex and time-consuming than any engineering team appreciates.
Tight coupling between pricing models and application logic can create a significant overhead which usually means the pricing model won’t be changed often… and it might sound ridiculous, but many organizations ignore this problem and continue to suffer from an outdated and anchored pricing model because of bad software design choices in the early days of the company.
This article introduces entitlements, an elegant solution to a complex problem in software monetization, and what engineering teams need to know to utilize it effectively.
Table of Content:
→ 1.1 Definition
→ 1.2 Entitlement checks
→ 1.3 What they are not
→ 4.1 Plan identifiers
→ 4.2 Authorization
→ 4.3 Feature flags
So, what are entitlements
By focusing on features instead of pricing concepts, we can decouple the price model from the application logic. The concept of Entitlements encapsulates the feature access settings under various product variants (aka Pricing Plans or Packages), bridging the gap between how a product is sold and how it behaves for a variant.
In essence, entitlements are a set of permissions defining what a customer (paying or non-paying) can do with your software application. For example, an entitlement can grant the customer access to the “Audit logs” feature or limit their account to “5 seats” within a given plan.
In essence, entitlements are a set of permissions defining what a customer (paying or non-paying) can do with your software application.
Entitlements provide a clean separation of concerns, effectively streamlining the process of updating product features in response to changes in the pricing model.
The 3 types of entitlements and how to control access using entitlement checks
Entitlement checks are vital to accurately control and monitor the access and usage of features by customers. They ensure that customers are granted access to the features they’ve paid for and help prevent overuse or misuse of resources.
To have some common ground on how are the checks are evaluated, lets present an example of a basic entitlements data structure granted to a customer:
These are the 3 most common types of entitlements in SaaS and how entitlement checks work for each of them:
Sometimes referred to as binary flags, these types of entitlements control whether a customer has access to a specific feature or not. For instance, a customer on a free plan might not have access to advanced analytics, but upgrading to a paid plan will enable this feature. These binary flags simply gate the feature—either the customer has access, or they don't.
Feature access is controlled by evaluating a condition at runtime based on the customer and feature identifiers. This check verifies whether the customer is entitled to access the particular feature or not.
This type of entitlement changes the behavior of a feature within the application, depending on the package or plan that a customer is on. For instance, a customer on a free plan of an observability tool might have the data retention policy set to 3 days, while a customer on a paid plan might have a longer retention of 14 days. The entitlement does not just control access, but also how the feature behaves within the application.
For configuration entitlements, the check doesn't just involve whether or not the feature is present, but also retrieves a configuration value that drives application behavior.
These entitlements cap the metered usage of certain features. In case of hard limits, access is fully cut off, once the limit is reached. For example, a customer has access to 5 seats. Once they reach 5 seats, they can’t invite more users. In case of soft limits, customers are alerted or throttled once they reach a certain usage level. For example, a customer may be limited to 1000 API calls per day under a free plan. Once the customer crosses the limit a "Maximum capacity reached" email is automatically sent, and a significantly lower API rate limit (or a grace period) is applied before the API starts rejecting new data.
In the case of metered entitlements that have soft or hard limits, these checks are performed against the expected usage (= current usage + new usage) in a per-request context. For hard limit checks, it’s crucial to prevent overages, so real-time data is essential for accuracy.
For soft limit checks, where preventing an overage is less important, there’s some tolerance for eventual consistency. This means you can compare against cached or slightly stale usage, offering a balance between system performance and accurate usage tracking.
What entitlements are not
To fully understand what entitlements are, let’s cover some misconceptions about them as well.
Firstly, entitlements are not a customer setting. Entitlements are typically part of a contractual agreement between you and your customer, i.e. the plan the customer chose. Customer settings are individual configurations a customer can make within their account. For example, a customer pays for 1GB of log data per day. One of their applications in their development environment is spammy. The customer setting allows them to reduce the log data for this specific environment to 256mb, while the account is still entitled to 1GB in total.
Secondly, entitlements are not synonymous with plans, e.g. "Basic", "Pro", and "Enterprise". Entitlements are, at their core, marketable features. Different pricing plans may grant access to these features with various configurations, but an entitlement does not inherently represent a particular product level.
Why should you care about entitlements
Managing pricing changes at the code level, without appropriate abstraction mechanisms, can quickly devolve into a tangled mess, resulting in more complexities than anticipated.
With entitlements, you can cleanly decouple the pricing model from the application logic, enabling swifter and smoother changes to your offerings. Any packaging change will take a fraction of the time you’d spend with hardcoded checks.
Besides taking much less of your time, you will make your organization that much more flexible in the way they go to market. You can introduce new features or tweak existing ones without having to overhaul the entire system. You’ll be able to quickly adapt to changes in the market, customer needs, or business strategies. This agility not only gives you a competitive edge but also makes for a better user experience as you can tailor your offerings to better suit your customers' needs.
On top of that, entitlements enable GTM teams to A/B test and experiment with pricing & packaging, without talking to developers at all. As outlined in the beginning of the article, SaaS pricing & packaging has to change regularly to keep up with market dynamic. As an abstraction on top of your codebase, those changes will no longer require you to write code.
As an abstraction on top of your codebase, those changes will no longer require you to write code.
Adopting entitlements can save you tons of development hours, less bugs, and increase your chances of success in a rapidly changing market environment.
Fusing entitlements and metering
Metering becomes crucial, once your pricing model includes configuration or soft/hard limit entitlements. Say you limit your customers by the number of users they can add to their team, the amount of storage space they get access to, or the number of API calls they can make within a certain timeframe. Without measuring a customer’s usage of an entitlement, you won’t be able to enforce limits in the entitlement service, and the enforcement will have to leak into the application code. For example, a customer’s plan includes 5 seats. Without metering, you won’t know how many seats they actually use. Your customer could invite 30 other users, without being limited - or ever having a reason to upgrade.
Without measuring a customer’s usage of an entitlement, you won’t be able to enforce limits in the entitlement service, and the enforcement will have to leak into the application code.
Metering software is designed to calculate feature usage, based on raw measurements that are often stored in an append-only system. This way, it is possible to maintain a historical record and allows querying for historical usage between different timeframes.
If you don't have a metering solution in place, you'll need to calculate the usage yourself. For simple counting, this is fairly straightforward – you just query your database to figure out how many instances of a feature or resource exist and compare it with the limit set by the entitlement.
However, when your usage is interval-based (such as a limit on API calls per month), it becomes more tricky. You need to design a system that can aggregate usage data for every passing interval, and that can correctly reset or roll-over counts when the interval ends.
For example, to support the entitlement, you’ll need to track and count the number of API calls:
For entitlements with hard limits, once the limit is reached, access to the feature must be revoked to prevent any overuse. This is especially relevant for free plans. Hard stops also introduce perfect upsell opportunities, whether you support a self-service or sales-led model. For self-service products, present a paywall for your customer to allow them to upgrade and overcome the limit they’ve just experienced. For sales-led products, you can trigger a notification to your sales team to reach out to their customer.
Optimizing plans for success
Metering isn't just about enforcing entitlements. It's also a powerful analytical tool. By analyzing usage patterns, you can gain insights into how different features or resources are being used. This can inform decisions about how to optimize entitlement limits for future pricing packages and enables modern ways to go to market, such as hybrid pricing (i.e. combining fixed costs with limits and variable costs into a new pricing model).
Pro Tip: When talking about optimizing pricing plans, GTM teams will need a way to experiment with different versions of a plan. A good entitlement service should allow changing the upsell interface (e.g. paywalls or trial banners) dynamically to easily accommodate those experiments without additional coding.
Entitlements vs Billing
Billing software has a very specific role in managing financial transactions, invoicing, payment scheduling, and processing. Simply put, they handle everything when a customer swipes their credit card. In pricing & packaging, especially in self-service products, a lot is happening before and after that swipe, though. Many times, users first access your product through a free plan or trial period. Complex upgrade & downgrade flows require very smooth controls over who has access to what feature.
The key distinction between the two systems is that while billing software is focused on the commercial aspect, entitlements are all about provisioning and access control.
The key distinction between the two systems is that while billing software is focused on the commercial aspect, entitlements are all about provisioning and access control.
Why does your entitlement service have to be separated from your billing?
Bridging between application and billing
An entitlement service can be seen as a bridge between your application behavior and your billing process, and can become the source of truth for both pricing and packaging. Besides acting as an “anti-corruption layer” to shield potential integration errors with the billing software, it also provides a fail-safe layer in case the billing system is unreachable. If the need rises, this can allow you to switch between billing solutions in the future easier with much less coupling.
Dealing with legacy plans
Billing systems typically do not handle the concept of "grandfathering" (i.e. allowing legacy customers to stay on their plan, while updating the plan for new customers), or gradually transitioning customers from legacy plans to the new ones (e.g. when you add a new feature to an existing plan). There is also no native support for scheduling migrations of customer segments, so moving e.g. your legacy customers to the new plan at the end of their billing period will be pretty hard doing it, involving custom scripts and programmatically scheduling the transition. Entitlement services can automate this process, reducing the manual effort and ensuring a smoother transition for customers.
Centralized entitlement management
The main benefit of an entitlement service is that it allows you to manage each feature's business logic centrally. It's an independent system that decides who has access to what based on the user's subscription status. Billing software, on the other hand, isn't designed to carry out these checks or grant access to features. It's solely concerned with financial transactions.
Scalability and low latency
Entitlement checks are crucial for ensuring that applications operate reliably. These checks need to be made quickly and efficiently, which requires a system designed with low latency and scalability in mind. Billing systems typically don't offer this kind of performance because they delegate these concerns to the integrating system.
Flexible access management
An entitlement service allows for a much greater level of flexibility when it comes to managing user access. It can handle multiple sources of access rights, such as subscription plans, add-ons, and ad-hoc features (like promotions) granted to a customer. Billing systems are far more limited, as they’re focused on pricing and payment, not on deciding who gets access to what.
Decoupling pricing and access control
By separating entitlements from billing, you can decouple pricing from access control. With this separation, you can give users access to features independently of their billing status, offering more flexibility and control for use-cases like free & reverse trials, and customisations for enterprise customers.
Enforcing plan immutability
Billing systems usually don’t have safeguards to control changes of an existing plan. If one of your team members makes a change unintentionally, this will affect all your existing customers immediately. An entitlement service ensures that plan details are immutable, providing peace of mind for both operators and customers by preventing unexpected changes.
Development, Staging and Production environments
Billing systems often lack support for different environments or the development release lifecycle. For changes in your pricing model, whether you add or remove a feature, update the price or overhaul your entire model, you’ll probably want to build in development, test in staging, and only then move to production. Billing systems offer limited support for change management, delegating the tedious tasks of seeding data and syncing it between multiple development accounts to you. An entitlement service should support multiple environments and allow automatically promoting changes between different development, staging, and production in order to prevent potential drift.
Alternative approaches: The shortcomings of plan identifiers, authorization, and feature flags
Today, you might already use a number of concepts, which may seem like a proper solution to solve monetization challenges. Let’s discuss a few alternatives to entitlements, and the limitations and friction points you should be aware of.
Entitlements vs Plan identifiers
A common approach, especially in early-stage SaaS startups, is to tie access control to plan identifiers, that is, checking the user's subscription plan to determine access to specific features.
For example, a structure like this can be found in the early days of a company:
While this might seem like a straightforward solution, it has significant downsides that can lead to complexity and rigidity over time.
Brittleness of plan identifiers
Plan identifiers can make your code brittle. The major drawback lies in the tight coupling it creates between your pricing model and the application codebase. Any change in the pricing plan, from changing the name of a plan, to changing the price or modifying the packaging, implies changes to the product behavior, which in turn necessitates updates to the code to accommodate it.
Coupling the feature access logic with the pricing model will require changing the application code every time you want to adjust or change anything. That’s a lot of maintenance work you can save by decoupling plans and features. Your entitlement checks should only be concerned with whether a customer has access to a feature, not why they have access. This separation of concerns is vital for maintaining clean, maintainable, and flexible code.
Changes and migrations
Another aspect to consider is customer migration between plans. Say, for example, your business introduces a new plan or updates an existing one, and you wish to move customers to this plan. With plan identifiers, you would need to sift through the entire codebase to update the plan reference, even if you only want to make a change in the entitlement configuration. A task prone to errors and bugs.
Custom settings for enterprise plans
Enterprises often require custom settings that differ from standard plans, thus necessitating a unique plan. With plan identifiers, you'd need to create a new plan for each custom case, leading to a multitude of plans and identifiers that are difficult to manage and reason about.
Custom code for usage and limits
When you use plan identifiers, tracking feature usage or metering requires implementing usage limits in your codebase. This adds another layer of complexity, leading to a potential maintenance burden over time.
Entitlements vs Authorization
Authorization is a method of restricting system access based on certain rules, such as role-based (RBAC), policy-based (PBAC), or attribute-based (ABAC) access controls, of individual users within an application.
While entitlements serve monetization, typically on account level, and authorization serve access control, typically on user level, it's possible to model entitlements using an authorization concept by mapping plans to roles, attributes or policies. Here is an example, the free and premium plans are mapped as roles, with each role having a set of entitlements modeled as permissions:
While this approach may work for less complex pricing models for a while, here are a few downsides you should be aware of.
User access vs account access
Authorization follows the principle of "least privilege," providing only the minimum access rights needed for a user to fulfill their role. Authorization isn't tied to the business model of a product, but rather to the organizational structure within which a product or system is used. For example, in a typical SaaS product, a user with the Admin role may have access to invite add or remove team members, while a user with the Member role may not.
No support of usage limits
Usage limits are not natively supported in authorization. While some advanced authorization policy engines can support this use-case, it's not a first-class citizen in most authorization implementations.
An example of how to implement entitlements using the Oso policy engine (example from Oso's docs):
This approach will only work for monolithic applications, where the policy is evaluated against a single database. In distributed applications or microservices, where each service owns a subset of the policy’s data, accessing the usage can become even more challenging.
Entitlements and JWT
Some might consider storing customer entitlements on authentication tokens, like JWT, by writing custom claims or permissions as part of the token’s payload. Take into account that this method won’t be accurate enough for most monetization use cases. JWT tokens are stateless and are not typically updated until they're refreshed.
This can be problematic for several reasons:
- Usage limits won’t be accurately updated. If a user purchased another seat - the entitlement limit should be increased immediately.
- If you enrich the JWT payload with current usage, it won’t be accurately tracked. For example, a user exceeds their limit, but it won’t be reflected or blocked in time.
- If a user upgrades or downgrades to a different plan, they won’t have instant access to the new entitlements.
- If the company wants to grant a promotional entitlement to an account or change a user’s plan, those changes won’t be reflected in the user’s token immediately.
This can lead to inaccurate or outdated permissions being enforced.
Entitlements vs Feature Flags
Feature flags, also known as feature toggles, are a technique used in software development to turn certain features on or off at runtime, without needing to change or redeploy code. They are originally intended to be short lived and removed from the codebase, when not in use anymore.
While both feature flags and entitlements provide control over software functionality, entitlements offer more sophisticated controls such as usage limits and tiered access levels that are automatically updated when a plan changes.
An example of an entitlement check can be performed using a LaunchDarkly SDK:
The evolution of Permissioning Toggles
Feature flags allow developers to turn features on or off, providing a way to test and release features gradually, perform A/B testing, and more. When considering entitlements in comparison, we could view them as an evolution of Permissioning Toggles. However, they specifically cater to marketable features sold under various subscription packages, extending beyond the binary on/off use-case of traditional feature flags.
When compared to other types of toggles, the nature of entitlements is relatively high dynamism (i.e. when the toggle value changes) as they are tied to the pricing model and customer subscription level, and a longevity (i.e. how long the toggle exists in the codebase) that can span from at least a few months to a few years.
You can read more about the different types of feature toggles in this excellent article by Pete Hodgson that was published on Martin Fowler’s website.
If you choose to use a feature flagging system to manage your entitlements, here are a few things you need to consider.
Deterministic changes in entitlements
Feature flags are not part of the customer's contract and don’t have any financial impact. These flags can be used to test new features or variations with a subset of users, hence, they can be altered on the fly. Entitlements, on the other hand, are charged for and are bound by contract terms with a customer. Unlike feature flags that can be altered on the fly, entitlements change whenever a customer’s subscription or contract changes. Changes to entitlements usually require advance notice, and the current entitlements are typically only revoked after a sufficient “grace period” has expired. They are deterministic and should not be assigned ad-hoc, except in explicitly intended circumstances like for enterprise customers.
The core of a feature flagging system is targeting rules among users (or customers), segments (or subscription tiers), and features. This could mean building custom automation workflows to keep everything synchronized when a plan or subscription changes. Entitlements, on the other hand, are natively tied to the customer subscription, automatically updating any changes.
Ease of use
Feature flagging tools are typically more technical and primarily targeted at engineers and product managers. This means Customer Success and Sales teams often find them difficult to navigate and understand, reducing their overall effectiveness for those teams.
Again, custom code for usage and limits
Feature flags don't inherently account for feature usage or metering. As a result, to track feature limits, you might need to define those limits into your codebase and automate toggling of flags when those limits are reached.
Entitlements, Feature Flags, and Authorization: Stitching it all together
While it’s possible to duct-tape a solution to support your pricing model with one of the alternatives listed above, none of them will be sufficient enough on their own. Authorization, RBAC, and Entitlements each serve different purposes, are operated by different departments, and play a part in significantly different processes. To decide which tools you’ll need in your own stack, here’s an overview.
Feature Flags: Primarily managed by Engineering and Product teams. They form part of the software delivery and product management process. A good use case for feature flags is, if you have a user that you want to include into the release of a beta feature and you’re not yet ready to roll it out across your entire user base.
Entitlements: Managed by Product, Sales, Marketing, and/or Growth teams. They form part of the pricing and packaging strategies, and customer contract management processes. A good use case is, if you have a feature you’re ready to monetize, and you want to roll it out to all existing and/or new customers.
Permissions (Authz): Usually managed by the application administrators. They form part of the data security and compliance processes. A good use case is, if you want to enable customers to set different permissions for different users within a given account.
A typical sequence of access checks in the code would start with a feature flag check at the user level. This determines whether the feature is enabled for this particular user or organization.
If the feature is enabled, the system then checks the entitlements at the organization level to confirm that the customer's subscription includes access to this feature.
Finally, the system checks the user's role-based permissions to ensure that the user is authorized to perform the requested operation within the feature.
If we’ll imagine this sequence in code within a React application, it will look similar to this:
To stitch these three systems together and make sense of them, one practical approach is to create a centralized place for access checks, such as an API gateway. This gateway can take on the responsibility of authorizing operations using a "scatter-gather" pattern on the backend.
It "scatters" the authorization checks across the feature flag, entitlement, and permission systems, then "gathers" the results to make an overall decision. It can also pass this context on the request to downstream services so they won't have to fetch this data again in case they need it for their internal logic.
This approach encapsulates the complexity of the authorization checks and provides a unified interface to the rest of the application. It also allows for easier updates and changes as the underlying systems evolve.
An example of a “stitched” user data including feature flags, permissions and entitlements:
Best practices when working with entitlements
Entitlements are a crucial aspect of any SaaS pricing & packaging. We’ve summarized a few tips we found crucial when working with entitlements.
1. Don’t nest entitlement checks
As you work with entitlements, one key principle to follow is to avoid nesting entitlement checks within your codebase. Nesting checks can lead to complex logic that is hard to follow, manage, and debug. Moreover, it can create interdependencies, where changes in one entitlement can unintentionally affect others.
Instead of nested checks, we recommend introducing a new entitlement, if possible, instead of depending on many entitlements. If that's not an option, at least you can introduce an abstraction that wraps those entitlement checks as a single function to better deal with this kind of coupling, and make it easier to change in the future. A singular check streamlines your code and makes it easier to understand and maintain.
Example of alternatives to nested entitlement checks:
2. Never assume new entitlements are ‘there’
Due to the dynamic nature of entitlements, and the fact that they can be moved between plans, there is a chance an entitlement won't be present at all anymore.
Never assume that there are “mandatory” entitlements to ensure the application can continue to work properly. This will make your application less fragile and less subject to errors due to miss-configuration of entitlements.
Let’s say, you’ve added a new entitlement to a new version of your Free plan in your development environment. You can’t expect that this entitlement will be available until you’ll finish migrating all of your free customers to this new plan version. In the meantime, if the new entitlement check was already deployed - it must accommodate the fact that the entitlement is missing, or else the application will break.
3. Embrace the “fail open” principle
Entitlements are a critical component of any infrastructure. It's crucial to account for potential service disruptions. The "fail open" principle states that in the event of a failure, default access permissions should grant the user as much access as possible without breaking the application invariants. This ensures that users can continue to access necessary services, even when your entitlement service encounters an issue.
4. Create a centralized module in the code that evaluates the entitlements
In general, it’s good practice to keep the entitlement checks at bay by introducing a shared module or a class that encapsulates the checks for different features. This type of will make it much easier to track and change entitlement-related logic. It also helps define a more “business centric” terminology, when using entitlements in different areas of the application.
Think about this scenario. You have an entitlement ‘seats’. Inside your application, there is a members page for your customers to invite more team members. The invite button is enabled if the number of members is below the entitlement limit. Introducing a `canInviteMembers(numOfNewMembers)` function that checks for the seats entitlement against the current usage of the entitlement can help simplify the access check logic and re-use it throughout other places in the application.
This is just a recommendation. You’ll need to adjust it to your project’s coding standards.
5. Less is more
This might sound obvious, but way too often, this gets out of hand… Just like feature flags, if you don’t keep your entitlements as clean and simple as possible, you’ll end up with messy code. If an entitlement does not exist anymore, first remove the entitlement checks in all the places from the codebase, and then the corresponding entitlement.
Building an entitlement service:
Once your product is mature enough you’ll probably need an entitlement service.
Here are a few points that you should take into consideration before attempting to build one yourself:
1. Prepare for network latency and downtime
Every network call adds latency to the overall system response time. Entitlements are a critical function in the service you provide. You don’t want your customers to face long response times when trying to access a feature inside your product. Always strive to optimize your entitlement service for low latency and scale, or at least make sure you have a good caching mechanism in-place.
2. Communicate usage and limits
Especially in self-service products, your customers need to be aware of their current usage and the limits of their subscription, before they are being denied access to functionalities or service. An effective entitlement service should be able to track and communicate this information clearly to users. That can be through dashboards, a self-service customer portal, or regular in-app / email notifications.
3. Determine your source of truth
You’ll need a source of truth. Deciding between your billing provider and your entitlement service is a significant consideration. This decision will influence how you synchronize data between the two systems. If your entitlement service includes complex logic like complex trials, scheduled downgrades, or grandfathering, this will be more suitable as your source of truth. Conversely, if your billing system is more sophisticated, then it should be the primary data source. The key is to identify which system contains the most comprehensive and accurate representation of customer data and use it to drive your entitlement decisions.
To wrap up
Operating in highly dynamic markets, SaaS companies have much less chances of success when compromising on rigid pricing models managed in the codebase.
Entitlements are the base for a truly flexible taxonomy and speed in go to market, allowing developers to quickly build and update pricing and giving GTM teams the opportunity to experiment with pricing & packaging, without code.
We made it our mission at Stigg to solve entitlements for SaaS. Our API gives you a flexible and scalable infrastructure, including metering, built-in experiments, a bunch of snap-in widgets, and native billing integrations, out of the box, and provides the automation to orchestrate everything about your pricing & packaging. If you consider buying over building, check out our Free plan. You can use one of our sandboxes to see all functionalities of Stigg, even before integrating it.