One of the fastest ways to paint yourself into a corner in SaaS billing is to use commercial plan names as if they were product capability definitions.

At first it feels convenient:

  • free
  • pro
  • orgs

Then the business evolves.

Now you have:

  • legacy plans
  • promotional states
  • organization-paid members
  • personal subscriptions that predate org creation
  • features that should unlock for some users but not all users on the same commercial relationship

That is when simple plan checks turn into product bugs.

At Trek Point, we ended up needing an entitlement layer, not because we wanted abstraction for its own sake, but because commercial billing state and user capability state are not the same thing.

The Most Important Distinction We Had to Make

An organization might pay for a seat that gives a member “pro-like” product access without making that member an “orgs subscriber” in the same semantic sense as an owner or personally billed org customer.

That sounds like nuance. It was actually core product behavior.

In our entitlement model:

  • a personal org-tier subscription can map to orgs
  • an active org member covered by an org subscription inherits pro
  • both may have access to premium route-planning features
  • but they are not the same thing in product semantics

Why does that matter? Because commercial ownership and feature availability answer different questions.

  • “Who is paying?” is a billing question.
  • “What can this user do right now?” is an entitlement question.

If you collapse them into one field, you eventually ship nonsense.

Product Features Rarely Line Up With Pricing Names

The route planner is a good example.

Users do not think in terms of “I am on the orgs plan, therefore I should see enum value X.” They think in terms of capabilities:

  • can I use 3D maps?
  • can I export FIT or GeoJSON?
  • can I exceed the free waypoint limit?
  • can I keep exporting GPX this month?

Those are entitlement decisions.

They can be influenced by billing state, but they are not reducible to it.

That is why Trek Point’s paygate logic lives around concrete capability checks rather than scattered string comparisons against plan ids.

Why This Helped the API Too

Once you expose parts of your product through APIs, weak plan checks become even more dangerous.

A UI bug can be annoying. An API inconsistency becomes a contract problem.

Because Trek Point’s entitlement logic sits behind helper functions, we can apply the same capability model across:

  • server-rendered templates
  • JSON planner responses
  • route export endpoints
  • activity export limits

That is the unglamorous advantage of a real entitlement layer: the product behaves consistently no matter how it is accessed.

Legacy Plans Force Honesty

One reason I am skeptical of plan-name checks is that production systems accumulate history.

Trek Point still has to care about older commercial identifiers like teams, and product semantics have to survive those migrations. The entitlement layer let us say:

“Whatever billing path got you here, what matters now is the capability set we want to grant.”

That is much easier to reason about than letting legacy commercial ids leak into every product decision.

The Best Test in This Area Wasn’t About Billing

One of the tests I like most in this codebase verifies that an org member covered by an org subscription gets pro capabilities, not orgs.

That is a great test because it captures product intent, not implementation trivia.

It is asserting that we care about the user experience of access, while still preserving the distinction between the person who commercially owns the org subscription and the people benefiting from it.

In other words, the test is really about product language encoded as backend behavior.

What I’d Recommend to Other Teams

If your SaaS has more than one paid tier, build the entitlement model earlier than feels necessary.

You do not need a giant policy engine. You do need a place where you can answer:

  • what can this user do?
  • why can they do it?
  • does that capability come from personal billing, org membership, trial state, or legacy migration?

If you cannot answer those questions centrally, your paywalls are probably already drifting.

The Real Lesson

Pricing is a business abstraction. Entitlements are a product abstraction.

They influence each other, but they are not interchangeable.

Trek Point got more robust once we stopped asking “what plan is this user on?” and started asking “what experience should this user receive right now, and what is the valid reason for that access?”

That is a better question technically, and a much better question product-wise.