[Knowledge-sharing] True-ups

# True-ups

## What are True-ups?

True-ups are the outstanding overage of maximum users exceeding the users/seats in a license of a self-managed subscription. Any overages during the subscription term need to be resolved by purchasing additional seats for the subscription. True-ups are handled as an add-on product to the subscription during renewal. They are validated when the new license is applied to a self-managed instance.

### How to find the overage

There are two places within a self-managed instance where the overage is displayed:
1. Visit the admin dashboard (`/admin`) and look for the `License overview` section. A box displays the overage number as `USERS OVER LICENSE`.
   <details>
   ![admin_dashboard](/uploads/2a4e2bffda091bdafcff3611f1423935/admin_dashboard.png)
   </details>
2. Visit the subscription page (`/admin/subscription`) to find a similar box as on the admin dashboard that displays the overage number as `USERS OVER SUBSCRIPTION`.
   <details>
   ![subscription](/uploads/e5f7c8f6201814dd0112d90a6ef6f34d/subscription.png)
   </details>


## Quarterly reconciliations

Quarterly reconciliations is a feature that is offered within Cloud Licenses. If enabled, a self-managed instance will send seat link information to CustomersDot on a daily basis. This information includes a count of active users and a historical maximum user count.

The manual true-up process is replaced by an automated quarterly reconciliation process which uses the information from the daily seat link sync to amend subscriptions with any additional users added within the past quarter.

### Difference to quarterly reconciliations (QSR)

True-ups are an annual process which means that users over the license needs to be paid for the whole subscription term. When the users were added is not important for this.

Quarterly reconciliations are performed quarterly. Any users over the license needs to be paid for for the remaining subscription term only. This process can result in substantial savings.

See [this documentation](https://docs.gitlab.com/ee/subscriptions/quarterly_reconciliation.html) for an example on the difference in costs.

## CustomersDot

### Subscription renewal

When renewing a self-managed subscription, a section for true-ups will be displayed. The customer is required to enter their current users over the license. Otherwise the license created for the renewal might not work on their instance (might will be explained in the GitLab section).

<details>
![renewal](/uploads/966d6de03d0ed59abbf4b6a3a2663599/renewal.png)
</details>

True-ups are handled as an add-on product to the subscription. [This code](https://gitlab.com/gitlab-org/customers-gitlab-com/-/blob/a0bd9c8aa410b0e3c924d17a9240db2644ff2e1b/app/services/amend_subscription_service.rb#L162-186) applies the true-up product if required.

When the license is created for the renewal, [the code](https://gitlab.com/gitlab-org/customers-gitlab-com/-/blob/a0bd9c8aa410b0e3c924d17a9240db2644ff2e1b/app/models/license.rb#L82) checks if true-up info needs to be set. This is only the case if the true-up quantity is greater than 0 and the license has a term end date. If it is the case, the true-up date range [is automatically set](https://gitlab.com/gitlab-org/customers-gitlab-com/-/blob/a0bd9c8aa410b0e3c924d17a9240db2644ff2e1b/app/models/license.rb#L160-165) to the year prior to the current subscription term.

### Manual license creation

When creating a license manually in the Admin, the true-up count can be filled in during the creation as an optional field. Similar to the renewal process, the overage number has to be sufficient to cover the current overage of an instance.

<details>
![license_creation](/uploads/811e3e93dc56cb71dcb2769c9290ae3f/license_creation.png)
</details>

## GitLab

When applying a license to a self-managed instance, [a validation](https://gitlab.com/gitlab-org/gitlab/-/blob/ba33e30e7295c3528e0eda559dc6768c3c90a257/ee/app/models/license.rb#L36) checks for a sufficient true-up count. This check is only executed if the true-up info is set and the flag `reconciliation_completed` (license restriction attribute) is not set to `true` in the license. If the latter is set to `true`, true-ups will be skipped due to a successful Q3 quarterly reconciliation.

The historical max during the given true-up date range is used for this validation ([code](https://gitlab.com/gitlab-org/gitlab/blob/ba33e30e7295c3528e0eda559dc6768c3c90a257/ee/app/models/license.rb#L502)). If a previous user count (license restriction attribute `previous_user_count`) is present in the license, the historical max subtracted by the previous user count equals the expected true-up count. If the previous user count is missing, the daily billable users count is used instead (there's a reported bug for this fallback in https://gitlab.com/gitlab-org/gitlab/-/issues/361345).

The expected true-up count is then compared to the true-up count set in the license plus an additional 10% overage threshold (hence the "might not work" phrasing in the CustomersDot section). The threshold part is only available in versions "%14.2"+. If it's greater or equal the restricted user count (license restriction attribute `active_user_count`) is validated. This validation adds an error to the user count if the restricted user count plus a 10% overage threshold is less than the restricted user count in the license. If the expected true-up count is less than the true-up count set in the license plus an additional 10% overage threshold, the true-up validation results in an error that is added to the base errors (errors that are not associated to a specific attribute).

## Documentation

- https://gitlab.com/gitlab-org/gitlab/-/blob/aaa552b248b3af6dd2a4de88173fff7bfe85f4e1/doc/subscriptions/self_managed/index.md#users-over-license
- https://gitlab.com/gitlab-org/gitlab/-/blob/30adf0ce90db1326e9e53388aae26b3266651033/doc/subscriptions/quarterly_reconciliation.md#quarterly-reconciliation-and-annual-true-ups
- https://gitlab.com/gitlab-org/fulfillment-meta/-/issues/510+
- https://about.gitlab.com/handbook/business-technology/enterprise-applications/quote-to-cash/troubleshooting/#true-ups-adding-seats-users

## Possible improvements

1. No documentation about true-ups in CustomersDot. Is documentation in GitLab already sufficient?
1. Consolidate different spellings of true-up. GitLab, CustomersDot and the handbook use a mix of `true-up`, `trueup` and `true up`. It looks like `true-up` is the spelling that is used for customer-facing content.
   * **Here's one merge request that refactors the spelling in CustomersDot docs: https://gitlab.com/gitlab-org/customers-gitlab-com/-/merge_requests/6225+**
1. A previous investigation suggested to loosen the true-up validation for Cloud Licenses or even skip it entirely. This is still under discussion though, see https://gitlab.com/gitlab-org/gitlab/-/issues/362076+.


## Knowledge sharing video

https://youtu.be/jfwOlYFRTy4

Story points: 3.0