Lots of SaaSs have a certain usage based limitations I.e an analytics service might allow 100 pageviews a month on the free tier, 1000 on pro tier, 10000 on enterprise, etc. This means usage needs to be tracked and reset every month. I’m wondering the best way to do that.
Payment webhook - Stripe and other payment gateways have webhooks that trigger on successful payment. This would be a great time to reset the users usage every month. Pros: Already triggered just need to listen for them, in sync with billing. Cons: outside dependency that could fail, free tier users don’t have subscription/payments, annual paying users would only trigger yearly.
CRON job - Just have a CRON job that runs every month to reset everyone’s usage to 0. Pros: pretty simple to implement, Cons: Outside dependency that could fail. Also when do you trigger it, 1 CRON job at the end of the month for everyone, or a specific job for each user to reset on their “billing anchor”.
In-app logic - Every time a users usage is checked it could also be reset if it’s a new month. Pros: No outside dependency/centralized logic, free users could use it, simple to implement. Cons: Could have very stale data in database if not frequently checked and updated.
How do you go about this?
another way to do it, is when you set up your database schema, store all usage rows in a "bucket". For example each usage row could have: customer_id, usage_total, time_bucket. An example time_bucket value would be '2022-07'. Every time you read or write usage, search for the current time bucket, which you can find with code like: (new Date()).toISOString().slice(0,7) . When the month rolls over then everyone would have zero usage again because no one has a row with time_bucket='2022-08' yet.
The reason I would pick that is that I hate any pattern where you are "zeroing out" information in the database. Zeroing it out is permanently destructive and you lose information that you might want later for trend analysis or debugging or financial bookkeeping. Better to have append-only patterns where old information is preserved.
Similar to @Dargon idea, I create a view that is made up of usage totals by month. Something like:
For IsTempMail, I just stored the request count and the date (YYYY-MM-DD) in the database. Every time a user sends an API request, I'll sum the total request count in the last 30 days, so a SUM of 30 records. It's quick and simple, and I can generate charts to show daily request counts (SUM with GROUP BY). I also have a daily cronjob to clean up old records.
For pageview count, if you don't want to do any analytics/report, I believe it's best to store it on a Redis server with the userId-month as key and expire after 1 month. It's much simpler and quicker (just send an incr command and get the total count).