openmeter icon indicating copy to clipboard operation
openmeter copied to clipboard

Time-based quotas + webhook events when quota is reached

Open binaryfire opened this issue 2 years ago • 3 comments

Preflight Checklist

  • [X] I have searched the issue tracker for an issue that matches the one I want to file, without success.

Problem Description

A lot of projects use quota-based billing instead of usage-based billing (eg. pay $X for Y credits/month). Currently the only way to implement this with OpenMeter is to make a GET request after every event to check the meter total. That's not very scalable.

Proposed Solution

This is how I imagine it would work:

  1. Each meter can have optional associated quotas with timeframes of Daily/Weekly/Monthly/Yearly/No timeframe. The timeframe determines when a quota resets.
  2. A webhook event is triggered when a quota is reached within the given timeframe. This can be used to inform another application that a quota has been reached.
  3. Allowing multiple quotas to be associated with each meter would let us trigger webhooks events for things warnings too.

Smaller and indie projects often prefer quotas because of the simpler billing model. I think adding this functionality would open up OpenMeter to a lot more developers.

PS. Another option could be returning the current meter's usage in the HTTP response when every event is posted. But I'm assuming that would require a database lookup on every event, which could get expensive.

Alternatives Considered

A simple Redis-based counter that is checked before each outgoing request is made.

Additional Information

No response

binaryfire avatar Jul 05 '23 07:07 binaryfire

Thank you for opening the issue; this makes sense. OpenMeter doesn't know about billing periods and not every company bills on the first month of the date, so we need some API where users can set up a billing anchor and duration (weekly, monthly, etc.) per customer. Basically, usage specific alerting.

Something like:

Meter ID Subject Anchor Period Threshold Webhook
api_calls user-id-1 2023-01-02 monthly 100 http://myapi/webhooks/overage
api_calls user-id-2 2023-01-11 monthly 500 http://myapi/webhooks/overage

But for that, you would need to register a threshold alert for each subscription. What do you think?

hekike avatar Jul 06 '23 00:07 hekike

Hi @hekike. That could certainly work and keeps things simple. I think we'd need a warning threshold as well. A warning webhook event would be required to implement logic to warn users when they are getting close to their limit.

But would it be better to define periods, thresholds and webhook URLs globally as "plans" and apply a plan + an anchor to individual subjects? In the vast majority of cases, a period / threshold / webhook combo would represent one tier for a specific product. Eg:

Product B

  • Silver - $10/month, 1000 credits
  • Gold - $20/month, 5000 credits
  • Webhook - https://myapp.com/webhooks/products/b/overage

If we define these globally it'd be easier to change them for all users when we change our pricing, plan limits or webhook endpoints. 2 possibilities:

  1. Separate "meters" and "plans" with an association between them:

Meter: b_api_calls

Plan ID: b_silver Meter ID: b_api_calls Period: Month Threshold: 1000 Warning threshold: 900 Webhook: https://myapp.com/webhooks/products/b/overage

Plan ID: b_gold Meter ID: b_api_calls Period: Month Threshold: 5000 Warning threshold: 4500 Webhook: https://myapp.com/webhooks/products/b/overage

  1. Different types of meters (eg. 'simple' and 'plan'). In this setup, we'd create separate meters for each period/threshold/webhook combo:

Meter ID: b_api_silver Period: Month Threshold: 5000 Warning threshold: 4500 Webhook: https://myapp.com/webhooks/products/b/overage

Meter ID: b_api_gold Period: Month Threshold: 5000 Warning threshold: 4500 Webhook: https://myapp.com/webhooks/products/b/overage

In either case, we'd be setting the anchor separately for each user/subject.

PS. I think "start_date" would be more user friendly than "anchor"

binaryfire avatar Jul 06 '23 10:07 binaryfire

Makes sense. Stripe uses anchor, for example, because billing periods can reset in specific scenarios and anchor changes. For example, when someone uses threshold-based billing. When a customer reaches the pre-set threshold, like $100, Stripe will generate an invoice and reset the billing anchor.

I think, in general, we need to find a way to trigger webhooks without going too much into billing or requiring OpenMeter to know too much about customers and billing.

hekike avatar Jul 11 '23 21:07 hekike