Expose per-user non-billable credits in the subscription usage API

What does this MR do and why?

The Total usage card on the GitLab Credits dashboard counts billable plus non-billable usage, but Usage by user and the user drill-down count billable usage only. The rows don't add up to the card, and users with only promotional usage (for example Orbit usage on an Orbit Promotional ELA subscription) aren't listed at all.

CustomersDot now returns a per-user nonBillableCreditsUsed next to the billable totalCreditsUsed (https://gitlab.com/gitlab-org/customers-gitlab-com/-/merge_requests/17683). This MR is the backend half of consuming it:

  • Client: GET_USERS_USAGE_QUERY and GET_CONSUMERS_QUERY select nonBillableCreditsUsed. While CustomersDot hasn't deployed the field, the client retries without it, the same way it already does for entityType, so this MR can merge before the CustomersDot change is live.
  • GraphQL: new nullable nonBillableCreditsUsed field on GitlabSubscriptionUsageUserUsage, read from the CustomersDot response by UserConsumptionStatistics. totalCreditsUsed stays billable-only on both sides so the API keeps a clean billable / non-billable split; the frontend adds the two.
  • Credits sort: UserUsage#users_sorted_by_credits_used keeps users whose billable + non-billable total is above 0, so promo-only users are listed. Until the frontend MR merges, such a user's row shows the billable 0, because today's frontend only reads totalCreditsUsed. That window is GitLab.com only and short; the frontend MR is stacked on this one.
  • Specs, GraphQL docs and introspection schema.

Frontend (Usage by user row and drill-down card adding the two) is in !265553 (merged), stacked on this branch. Split on purpose: GitLab.com deploys in rolling fashion, so a frontend that selected the field in the same release could reach a node that doesn't serve it yet. @gl_introduced only covers the self-managed version skew, not that window.

This is change E (backend) of the plan in #633154 (comment 4099142904).

Not changed here: the credits sort still comes from CustomersDot's wallet debits, so users whose only usage is non-billable are listed but sort last. ConsumersFinder returns every consumer with no usage threshold, so they are reached by paging; the GitLab-side filter was what dropped them. A sort by billable plus non-billable is the iteration-2 follow-up in the issue (pre-existing issue 2).

References

Screenshots or screen recordings

When CDot changes are NOT available When CDot changes ARE available
Screenshot_2026-10-28_at_07.49.21 Screenshot_2026-10-28_at_07.49.54

How to set up and validate locally

  1. Check out https://gitlab.com/gitlab-org/customers-gitlab-com/-/merge_requests/17683 in your local CustomersDot. Without it, the client falls back to the billable-only queries and nonBillableCreditsUsed is null.

  2. Set up GDK in SaaS mode with that CustomersDot, as in "How to set up and validate locally" in !260725 (merged).

  3. In CustomersDot, seed one user with billable and non-billable Orbit usage and another with non-billable usage only, then enrich and consume:

    bin/populate_usage_data -r 20 --realm SaaS --root-namespace-id <id> --user-id <user_a> --feature-qualified-name orbit_mcp --team-member --skip-reason promo
    bin/populate_usage_data -r 20 --realm SaaS --root-namespace-id <id> --user-id <user_a> --feature-qualified-name orbit_rest
    bin/populate_usage_data -r 20 --realm SaaS --root-namespace-id <id> --user-id <user_b> --feature-qualified-name orbit_mcp --team-member --skip-reason promo
  4. In /-/graphql-explorer, as a group owner:

    query {
      subscriptionUsage(namespacePath: "<group-path>") {
        usersUsage {
          users(sort: TOTAL_CREDITS_USED_DESC, first: 20) {
            nodes { username usage { totalCreditsUsed nonBillableCreditsUsed } }
          }
        }
      }
    }
  5. Both users are listed. User A has both figures; user B has totalCreditsUsed: 0 and a positive nonBillableCreditsUsed. Before this MR, user B was not returned.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Sheldon Led

Merge request reports

Loading
Loading