You launch an AI tool at Rs. 499 a month. Two hundred people sign up, most use it lightly, and then one account runs a few thousand document summaries in a week. Your provider bill that month is larger than the revenue from fifty customers.
This is the problem a credits model solves. A credits model prices each action by what it costs you, lets customers buy a pool of credits, and spends from the pool as they use the product, so heavy usage pays for itself. This post shows how to choose the unit, set credits per action, check margins, size a free tier, and build a ledger that doesn't leak. The numbers come from a script I ran on 2026-10-09. The cost inputs are assumptions I made up for illustration, not vendor prices, so replace them with your own measured costs (the API cost worked examples show how to measure them).
What is a credits model, and when is it the right fit?
A credit is a unit of your product's currency. Customers pay for a pack, you add credits to their balance, and each action deducts some. It sits between a flat subscription and raw pay-per-token billing.
It fits when:
- Cost per action varies a lot (a chat reply versus a 50-page document summary versus an image).
- Usage is spiky or heavy-tailed, so a flat plan overcharges light users and bleeds on heavy ones.
- You'd rather customers think in "tasks" than in tokens.
Skip it when your cost per user is small and predictable, when every action costs about the same, or when your customers are companies that want a fixed annual number for their budget. In those cases a plain plan with a fair-use limit is simpler and kinder.
Credits also change what you need to build: a balance, a ledger, a purchase flow and a "you're out of credits" experience. If you take payments in India, the purchase side is a normal one-time order; the Razorpay webhook handler shows how to grant credits safely when the payment succeeds.
How do you price each action in credits?
Start from cost, not from what feels neat.
- Measure your average provider cost per action type over real traffic. Include retries and the extra calls an action makes (a "summarise" may be three model calls).
- Choose a credit price so a pack gives a round number of credits. In my example, Rs. 499 buys 500 credits.
- Assign credits per action so that every action clears your target margin after payment fees.
My assumed numbers: chat reply costs Rs. 0.40, document summary Rs. 3.00, image Rs. 4.00. Razorpay's pricing page (downloaded 2026-10-09) shows a headline 2% plus GST for the payment gateway, but the same page carries promotional text (a free period and a "0% fee" banner) and a footnote of "Platform fee 2.15% + GST" for some instruments, so the page is not a clean single rate. I assumed 2% plus 18% GST on the fee, which makes 2.36% the payment cost; 18% is my assumption of the GST rate on fees, not something I confirmed on that page. Treat 2.36% as an input to replace with your own contract rate and your accountant's GST treatment.
The script's output:
== A. Margin per action if sold in credits ==
net revenue per credit after payment fee: Rs 0.9744
chat cost Rs 0.40 charged 1 credits net rev Rs 0.97 margin 59.0%
doc_summary cost Rs 3.00 charged 8 credits net rev Rs 7.80 margin 61.5%
image cost Rs 4.00 charged 10 credits net rev Rs 9.74 margin 59.0%
blended per request: cost Rs 0.840, credits 2.15
Two rules of thumb from this table, both mine rather than industry law:
- Keep the margin roughly even across actions. If one action is priced at 90 percent margin and another at 10, customers will drift to the cheap-to-them, expensive-to-you one.
- Round credits to integers, but never round in the customer's favour on your costliest action. An image costing 9.2 credits rounded down to 9 turns a 59 percent margin into a lower one at volume.
Also decide what happens when your provider changes prices. Credits per action are your lever: you can change what an action costs without changing what a pack costs, as long as you announce it. Keep the table in a config file, versioned, not scattered in code. Check model prices regularly, since this post's own inputs are placeholders.
Does a credits model actually protect margin?
I simulated 10,000 users with a heavy-tailed monthly request count (median 120, spread chosen by me) and compared two designs: a flat Rs. 499 plan with no limits, and credit packs of 500 credits where users buy as many packs as they need. The request mix was 85 percent chat, 10 percent summaries, 5 percent images. Seed 7, so you can rerun it.
== B. 10,000 simulated users, heavy-tailed usage (seed 7) ==
requests/user: median 120, p90 640, p99 2428, max 14422
top 10% of users cause 49.8% of provider cost; top 1% cause 14.1%
flat Rs 499/month: users losing money 1130 (11.3%), total margin Rs 2,555,493, margin % 52.5
credit packs of 500: users losing money 0 (0.0%), total margin Rs 6,449,872, margin % 73.6
Read it carefully, because this is easy to over-sell. What it shows: with this usage shape, one in nine flat-plan users costs more than they pay, and the heaviest tenth drive half your cost. A credits model removes the loss-making accounts by construction, since each pack carries a margin.
What it does not show: that you'll earn Rs. 6.4 million instead of Rs. 2.6 million. The two cases aren't comparable revenue. Under credits, heavy users pay many times Rs. 499, and in real life some of them would pay less, switch tools or leave. The simulation also assumes everyone uses a clean multiple of their credits, ignores churn, and invents the usage distribution. Treat it as a method (plug in your own usage logs) rather than a forecast.
A practical way to use your own data: export one month of per-user cost, sort it, and find the share of cost from the top 10 percent. If that share is above roughly a third, a flat plan is exposed. If it is flat across users, you may not need credits.
How should you structure packs and a monthly plan?
Two patterns work for small AI products:
| Pattern | Description | When it fits |
|---|---|---|
| Prepaid packs only | Customer buys 500, 2,000 or 10,000 credits when needed | Spiky users, low commitment, simplest to build |
| Plan with included credits | Fixed monthly price includes N credits; top-ups sold separately | You want recurring revenue and predictable customers |
For the second pattern in India, a recurring mandate has limits: a UPI AutoPay amount can't change after the debit notice, so bill the base plan through the mandate and sell extra credits as separate one-time purchases. That is covered in UPI AutoPay for AI SaaS.
Pack design tips, all judgement calls:
- Three packs is plenty. A good middle pack makes the large one look reasonable.
- Give a modest volume discount on the biggest pack, and run the margin table again with the discount applied. Don't discount below your worst action's margin.
- Show credits per task on the pricing page ("a document summary uses 8 credits"). Surprise is what makes people feel cheated.
- Roll over or expire? This is a legal, tax and trust question. Credits you've sold can be a liability on your books, and rules about expiry differ by place. Ask an accountant before you copy a competitor's terms, and state your policy at the point of purchase.
How many free credits should you give?
Fewer than you think. Free credits are a marketing cost paid in provider bills, and they attract people who create accounts just to harvest them.
My assumptions again: 30 free credits per signup, spent on the blended mix.
== C. Free credits and abuse ==
30 free credits = about 14.0 blended requests = Rs 11.72 provider cost per signup, if fully used
1,000 signups, all fully used: Rs 11,721
10,000 signups, all fully used: Rs 117,209
100,000 signups, all fully used: Rs 1,172,093
worst cost per free credit is 'chat': Rs 0.400/credit vs blended Rs 0.391/credit
if a bot spends all 30 free credits on 'chat': Rs 12.00 per fake account
100 fake accounts -> Rs 1,200
1,000 fake accounts -> Rs 12,000
10,000 fake accounts -> Rs 120,000
For the controls that limit that exposure, see rate limits and free-tier abuse prevention. Honest reading: in this example the action prices are balanced, so the worst case per free credit is only slightly worse than the average. If your pricing is lopsided, a script will find the action with the worst cost per credit and spend all its credits there. That's another reason to keep margins even.
The number to remember: free credits per signup times your cost per credit is what each fake account costs you. At Rs. 12 a head, 10,000 fake accounts is Rs. 1.2 lakh. Whether that matters depends on your funds, but it's easy to prevent most of it.
Controls that cost little (untested suggestions, since I have not run them against real abuse):
- Make the free grant small and tied to one first task, such as "enough to try the core feature once".
- Require a verified email, and a phone number if your audience is mostly in India and abuse appears. Block known disposable email domains with a list you maintain.
- Limit by IP and device, but expect shared networks. A hard IP cap will hit real students on a college network.
- Cap free accounts on expensive actions: let them chat, but not run images or long documents until they've bought a pack.
- Put a daily global ceiling on free spend that pages you when reached, so an attack costs a day, not a month.
- Give the free grant after the first meaningful activity, not on account creation.
Add a hard per-request token cap and a rate limit as a backstop, since credits only help once an action completes. The Claude API rate limits guide explains the provider side of limits you will hit yourself.
How do you keep a credits ledger correct?
The money lives in the ledger, so treat it like accounting: append-only rows, never edit a balance in place. Balance is the sum of the user's entries.
Three bugs I'd expect in a first version, and the fix for each:
- Overspend under concurrency. Two requests both read a balance of 10 and both spend 8. Fix: check and insert inside one transaction that takes a write lock.
- Double grants on payment retries. The gateway sends the same webhook twice. Fix: a unique key on the payment id.
- Charging for failed calls. The model call times out after you deducted credits. Fix: reserve first, then release the reservation on failure, with a unique key per request so a retried release can't pay out twice.
I tested the reserve pattern with SQLite and threads. The schema has a unique index on (user_id, reason, ref), grants and releases use INSERT OR IGNORE, and reserve takes BEGIN IMMEDIATE before checking the balance:
def reserve(user, n, ref):
c = conn()
try:
c.execute("BEGIN IMMEDIATE")
if balance(c, user) < n:
c.execute("ROLLBACK")
return False
c.execute(
"INSERT INTO ledger (user_id, delta, reason, ref) VALUES (?,?,?,?)",
(user, -n, "reserve", ref),
)
c.execute("COMMIT")
return True
finally:
c.close()
Run with a 10-credit grant and five parallel requests of 4 credits each:
10 credits, 5 parallel requests of 4 credits each -> accepted: 2 rejected: 3
balance: 2
after one failed call released twice (idempotent): 6
Two accepted, three rejected, and the balance never went negative. The duplicate release was ignored, so the refund of 4 applied once. In the demo I released a request id that may not have been one of the accepted ones, so read that last line as a test of the unique key, not of business logic. On Postgres, use a row lock on a balance row or a serialisable transaction; SQLite's single-writer lock is doing the work here.
After the call, settle: if the real cost was lower than the reserve (shorter output), release the difference with a distinct reference. Show the customer the final charge in a usage history screen. Support tickets about missing credits fall sharply when users can see an itemised log.
What mistakes make credits models fail?
- Hiding the unit. If customers can't guess what a credit buys, they won't buy a second pack. Show examples in the product.
- Pricing from list prices once. Provider prices and your own prompt length drift. Re-run the margin table monthly.
- One global free tier. Different cost actions need different free limits.
- No low-balance notice. Warn at 20 percent so a customer can top up before a task fails midway.
- Reading the simulation as truth. Everything above runs on my assumed costs. Your first month of real usage logs will replace them.
- Forgetting the rest of the business. Pricing is one part; our AI wrapper SaaS playbook covers moats, churn and go-to-market.
A quick checklist before you ship pricing
- Measured cost per action type, from real logs, with retries included.
- Credits per action table, with margin after payment fees and GST on fees.
- A pack ladder of three sizes and a stated policy on rollover or expiry, reviewed with an accountant.
- Free grant sized from the cost-per-signup arithmetic, with verification and a daily global cap.
- Reserve-then-settle ledger with unique keys per payment and per request.
- Usage history page and a low-balance email.
- A monthly job that recomputes margin per action from fresh costs.
Run the numbers on your own usage first. If the top tenth of your users are not driving a large share of cost, keep it simple and sell a plan.



