gitpod-io / gitpod

The developer platform for on-demand cloud development environments to create software faster and more securely.
https://www.gitpod.io
GNU Affero General Public License v3.0
12.74k stars 1.22k forks source link

[Usage-based] Implement a "Cost Center" entity #10757

Closed jankeromnes closed 2 years ago

jankeromnes commented 2 years ago

Is your feature request related to a problem? Please describe

Until now, we attribute workspace usage hours to Users or Teams directly (which themselves might map to a Stripe Customer).

But, as explained in this comment, it would be good to create an "indirection", and attribute workspace usage to a dedicated "Cost Center" entity.

Describe the behaviour you'd like

Describe alternatives you've considered

We currently attribute directly to a Team or a User. However, this makes some of the logic implicit (i.e. "if no attributed Team, default to workspace owner"), and does not allow future evolutions like sharing a Cost Center between multiple Teams, or having "Organization"-level Cost Centers (once "Organizations" exist)

Additional context

jankeromnes commented 2 years ago

A "Cost Center" entity could look something like this:

export interface CostCenter {
    id: string;
    stripeCustomerId?: string;
}

(The optional stripeCustomerId would only be relevant for when payments are enabled. But, we can also omit this field entirely, and simply query Stripe for customers with a specific costCenterIds. 💡)

export interface UserCostCenter extends CostCenter {
    userId: string;
}

export interface TeamCostCenter extends CostCenter {
    teamId: string;
}

This could be one way to differentiate between User Cost Centers and Team Cost Centers. Another option could be to simply add the two optional fields userId? and teamId? to the root entity, and somehow guarantee in code that only one of them is set at any given time. 💭

geropl commented 2 years ago

Hey @jankeromnes , thank you for creating an issues for this!

I feel we still need a bit of alignment before we dive into the implementation. I'm not sure about the naming, for instance. "Cost center" feels to me like a different meaning, and we came to use it because we put "Kostenstelle" into Google translate. :laughing: E.g., I like "billing account", because it's less ambiguous. But anyway, we should align on this one. :slightly_smiling_face:

jankeromnes commented 2 years ago

Hmm, you're right, some more alignment would be good. 😅

Personally, I quite like the term "cost center", as it also works well in english -- e.g. when booking flights for a company trip, you often need to select a "cost center" -- typically you choose the one that corresponds to your team. So, I think "cost center" is a good fit for this new concept.

In particular, I think it works well because "cost" does not necessarily mean "amount in currency" -- we can also talk more generally about cloud costs, e.g. in minutes/seconds/credits. This is compatible with Self-Hosted (e.g. you can track your costs across all teams/projects/users in your Self-Hosted install -- without having anything to do with billing or Stripe or whatever).

What I don't like about "billing account" is that this directly maps to payments -- e.g. I would expect a "billing account" to be something in Stripe. In Self-Hosted, you may want to track costs without any billing (e.g. just for accounting, or setting up per-team/per-project quotas, etc).

geropl commented 2 years ago

What I don't like about "billing account" is that this directly maps to payments -- e.g. I would expect a "billing account" to be something in Stripe. In Self-Hosted, you may want to track costs without any billing (e.g. just for accounting, or setting up per-team/per-project quotas, etc).

:bulb: Ah, that's a new perspective for me! I always thought about the concept to strictly be a "BillingService" (SaaS) concern. Have to think about the idea that it can also host quotas...

jankeromnes commented 2 years ago

Update: As an initial simplification, we've started by implementing a unique usageAttributionId (new column on d_b_workspace_instance):

10822

This sort of represents a "cost center" for workspace usage (but without a persisted "cost center" entity yet), and can either point to a Team or to a User, e.g.:

In the future, if we want to implement a "cost center" entity (for example, to persist limits or quota information), I suggest that we create a new table for them, and use the unique attribution ID as the primary key of that table, e.g.:

export interface CostCenter {
    id: string;
}

(Where id is of type varchar(60) and can either look like "team:..." or "user:..." -- thus there is no need for extra userId or teamId attributes.)

AlexTugarev commented 2 years ago

All workspace usage hours should get pre-attributed to a "Cost Center" instead of a Team

@geropl and @easyCZ, please help with clarifying this. What exactly is the expectation for this point?

geropl commented 2 years ago

All workspace usage hours should get pre-attributed to a "Cost Center" instead of a Team

@geropl and @easyCZ, please help with clarifying this. What exactly is the expectation for this point?

That's outdated here, and already happening, so should not be part of this task anymore.