Best practices for monthly usage resets with annual plans #971
Unanswered
marckohlbrugge
asked this question in
Q&A
Replies: 1 comment 2 replies
-
This is pretty close to what we do with metered billing for Hatchbox. We have a job that runs every few hours and records usage since the last update. Running every hour will be good for distributing credits throughout the day whenever someone had purchased which is good. And if cron didn't run for some reason, you'd be able to catch it in the next hour and their credits would only be behind a short bit. I wish that Stripe was able to take care of this for us and send webhooks monthly for annual plans! |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Many SaaS services have usage limits or credits that reset each month. When the customer is subscribed to a monthly plan, these monthly usage resets are easy to implement as we can simply listen for one of the monthly payment hooks our payment processor sends.
But what if the customer subscribes to an annual plan?
In many cases, you still want to run certain code like credit resets each month. But now we cannot rely on payment processor posting to our webhook each month at the right time.
What's a good approach to solve this issue?
Here's my current thinking:
Billing::UsagePeriod
(belongs_to :user, belongs_to :pay_subscription, starts_at:datetime, ends_at:datetime
) model which represents a single month of a user's usage.invoice.paid
webhook toBilling::UsagePeriod
with anafter_create_commit
callback that takes care of resetting the usage, issuing new credits, etc.invoice.paid
webhook is called, create a newBilling::UsagePeriod
Billing::UsagePeriod
recordThe hard part is finding the relevant subscriptions. The first billing period is already taken care of by our regular
invoice.paid
webhook for monthly payments.So we'll need to find subscriptions that are still
status = active
, and their most recentBilling::UsagePeriod
has anends_at
that's in the past.For example
What do you think of this approach? Are the other best practices to consider?
Beta Was this translation helpful? Give feedback.
All reactions