The Problem with Subscriptions for AI Products
If you're building an AI product, you've probably thought about billing. The obvious choice is subscriptions — $20/month, $50/month, etc.
But subscriptions don't work well for AI:
- Heavy users eat your margin. One power user can cost you $100/month in API calls on a $20 plan.
- Light users feel ripped off. They used the product twice and got charged $20.
- Unpredictable costs. You can't forecast your API spend when usage varies wildly.
That's why every major AI company uses credits or tokens: OpenAI, Anthropic, Replicate, ElevenLabs.
The Solution: Credits-Based Billing
I built ShipAI, a Next.js boilerplate with credits billing baked in. Here's how the system works.
The RESERVE → STREAM → FINALIZE Pattern
typescript
// Step 1: Reserve credits BEFORE the AI call
// Uses SELECT FOR UPDATE for atomic locking
const reservation = await supabase.rpc('reserve_credits', {
user_id: userId,
amount: estimatedCost
});
// Step 2: Stream the AI response
const stream = await openai.chat.completions.create({
model: 'gpt-4o',
messages,
stream: true
});
// Step 3: Count actual tokens and refund unused credits
await supabase.rpc('finalize_credits', {
user_id: userId,
reserved: estimatedCost,
actual: calculateCost(inputTokens, outputTokens, model)
});
This pattern ensures:
Users are never overcharged (unused credits are refunded)
You never give away free API calls (credits are reserved first)
No race conditions (SELECT FOR UPDATE provides row-level locking)
Per-Model Pricing
Different models have different costs. ShipAI handles this automatically:
Model Input (per 1K tokens) Output (per 1K tokens)
GPT-4o 1 credit 3 credits
GPT-4o Mini 0.5 credits 1 credit
Claude Sonnet 1 credit 3 credits
Claude Haiku 0.3 credits 0.8 credits
Users choose their model, and the credit cost adjusts automatically.
Security Considerations
Credits are money. They need to be treated like financial transactions:
CHECK constraint: credits >= 0 — credits can never go negative at the database level
Idempotent webhooks: Stripe can send duplicate events. The add_credits function uses stripe_session_id as a unique key to prevent double-crediting.
Row-Level Security: Users can only read their own credit balance and transaction history.
Input validation: Max 100 messages per request, 32KB payload limit.
The Full Stack
ShipAI includes everything you need beyond just billing:
Next.js 15 with App Router
Supabase Auth (email, Google OAuth, magic links)
Stripe Checkout with pre-configured webhooks
Multi-model chat UI with streaming responses
Usage dashboard with token tracking
TypeScript + Tailwind CSS
One-click Vercel deploy
Try It
ShipAI is available for $69 (launch price, regular $149): Get ShipAI
If you're building an AI product and don't want to spend weeks on billing infrastructure, check it out. Happy to answer questions in the comments.
Top comments (0)