If you're charging SaaS customers for the LLM usage your product incurs on their behalf, you have three architectural options, and picking the wrong one for your traffic pattern means either a Stripe bill you're paying out of margin or a support queue full of billing disputes.
Approach 1: Real-time metered billing
Every LLM call gets logged with its actual cost (tokens in, tokens out, cost in USD, customer ID) at the moment it completes. Once per day or per hour, aggregate usage and update Stripe:
async function syncUsageToStripe(customerId) {
const usage = await db.query(
`SELECT SUM(cost_usd) as total FROM llm_events
WHERE customer_id = $1 AND synced_to_stripe = false`,
[customerId]
);
await stripe.billing.meterEvents.create({
event_name: "llm_usage",
payload: {
stripe_customer_id: customer.stripeId,
value: Math.round(usage.total * 100), // Stripe meter events are integer units
},
});
await db.query(
`UPDATE llm_events SET synced_to_stripe = true WHERE customer_id = $1`,
[customerId]
);
}This is accurate — the customer pays exactly what they cost — but it means you're extending credit. The LLM provider bills you immediately; Stripe invoices your customer on a monthly cycle. A customer who churns mid-cycle or disputes the charge leaves you holding the API cost.
Approach 2: Prepaid credits (wallet balance)
The customer buys a credit balance up front — $50 of usage, for example — and each LLM call debits the balance in real time. This flips the credit risk: you're never out of pocket, because the call gets blocked once the balance hits zero.
async function chargeAndCall(customerId, estimatedCost, makeCall) {
const balance = await redis.get(`wallet:${customerId}`);
if (parseFloat(balance) < estimatedCost) {
throw new InsufficientBalanceError();
}
const response = await makeCall();
const actualCost = computeActualCost(response);
await redis.incrbyfloat(`wallet:${customerId}`, -actualCost);
return response;
}The tradeoff is friction: customers have to think about topping up a balance, which is an unfamiliar mental model for SaaS buyers used to a flat monthly invoice. It works best for usage-heavy, high-variance products (AI agents, document processing) where a flat tier would either overcharge light users or undercharge heavy ones.
Approach 3: Fixed tiers with overage
The customer pays a flat monthly fee that includes a usage allowance (e.g., $29/month includes 10,000 requests), and usage beyond the allowance bills at a per-unit overage rate, synced to Stripe the same way as Approach 1. This is the most familiar model for SaaS buyers and the easiest to market, but it requires you to set the allowance high enough to cover typical usage without eating your margin on the included tier — which means you need real usage data before you can price it correctly, not just a guess.
Which approach to use
Prepaid credits (Approach 2) is the safest default if you don't yet have usage data: it caps your downside to zero regardless of how a customer behaves. Fixed tiers (Approach 3) converts well once you have enough usage history to price the allowance correctly. Real-time metered billing (Approach 1) is the right model for enterprise customers with negotiated contracts and net-30 terms, where extending credit is already part of the relationship.
Whichever model you choose, the same enforcement problem sits underneath all three: you need to know the cost of a call, per customer, before you decide whether to allow it — not after the bill arrives.
Where noburn fits
The tools compared in this article handle observability, routing, or evaluation — all of which operate after the LLM call completes. noburn operates before it. It wraps your existing OpenAI, Anthropic, LangChain, and the Vercel AI SDK client, estimates the token cost of each call, and blocks it if the calling user or project has exceeded their budget. Nothing in this comparison does that at a self-serve price point.
Per-user metering lets you enforce separate limits per end-customer, and Stripe passthrough lets you bill them for their LLM usage without writing a billing layer yourself. The free tier covers 50,000 requests per month. Documentation and SDKs are at noburn.dev/docs.