The service I am building is usage-based, i.e.
* I am charging per second the service was used, e.g. USD 0.01/second
* I would like to give credits upon sign-up.
* There is no monthly minimum.
At the moment, I am thinking that I can achieve this with just a few tables:
* `billing_account (id, billing_rate_id, running_balance)`
* `billing_rate (id, rate)`
* `account_credit (id, billing_account_id, timestamp, amount, function_execution_id)`
* `account_debit (id, billing_account_id, timestamp, amount, source [platform_credit or stripe])`
When a user creates an account, I would create an entry in `billing_account` and associate whatever the current `billing_rate`. I would also create an `account_debit` entry with `source=platform_credit` and update `billing_account` `running_balance` value to reflect their balance after the `platform_credit`.
Then whenever they run a function that costs them, I create `account_credit` account with an entry equal to the amount they spent and update `billing_account` `running_balance` value.
When they top-up their account, I would just add entry to `account_debit` and update the balance again.
This appears to cover all my use cases, but I wanted to check with anyone who's designed such database schemas before.
Since you will want to plan for that, one thing you can do is treat the end of month billing calculation (or ongoing usage per day) as a calculation based off your raw usage logs.
So your usage of the product (service usage start/stop times) are log events (eg, pushed to S3 if its a huge system or start with just another database table like billing_usage_event) that describes each service start/stop and calculated rate etc.
Then your bill is the aggregation of the raw events for the day/month, allowing you to both do an audit if there is a billing query (find out why the bill spike occurred by looking at billing_usage_event) and also provide peace of mind to you and your customer the billing is accurate.
("Accounting for Developers" was posted recently on HN, it was a great read - https://news.ycombinator.com/item?id=32495724)