← Back to blog

Common issues with Stripe metered billing for AI products (and how to solve them)

Vesela Pavkovic

With an impressive background delivering payment solutions at companies like Skrill, Trustly and SumUp, Vesela has a deep understanding of what it takes to operationalise payments at scale. She is now leading a number of our Commercial Enablement initiatives.

Stripe metered billing works well for many SaaS products. But AI products have a property that changes the risk profile: the cost of a single request can range from fractions of a cent to several dollars. When one GPU inference call costs $1 or more, the standard post-paid billing model creates exposure that traditional subscription billing never had to deal with. This article covers the four places those risks show up and the practical fixes for each one.

Why does metered billing create risk for AI products?

Metered billing charges customers based on actual usage, tallied at the end of a billing cycle. In Stripe, this means usage events accumulate throughout the month and appear on an invoice that Stripe attempts to collect after the period closes.

For a product where each request costs $0.001 (a text API call, a simple lookup), the risk per customer is capped by volume. Even heavy abuse produces modest losses. But for products where each request costs $0.50 to $5.00 (image generation, video processing, GPU inference), a single customer can accumulate thousands of dollars in infrastructure costs before the first invoice is even generated.

The risk scales with two variables: cost per request and time between usage and payment. The higher either one, the more layers of protection you need.


How do fake accounts and payment fraud exploit AI signups?

The first attack surface is the front door. The dominant threat in 2026 isn't someone using a stolen Visa. It's fake accounts: synthetic identities, disposable emails, and multi-account abuse designed to consume expensive compute without ever paying.

Stripe's own data backs this up. Between November 2025 and February 2026, Stripe detected a 6.2x increase in abusive free trials across its network, with AI companies driving most of that spike. In the first two months of their new trial abuse controls, Stripe blocked over 550,000 high-risk free trials across just four AI businesses, preventing an estimated $4.4 million in compute losses.

Stolen cards are still a factor, but less so than they were. The number of stolen card records for sale dropped roughly 20% in 2025. In Europe and the UK, PSD2's Strong Customer Authentication mandate means most card-not-present transactions now require 3D Secure verification, which makes using a stolen card at signup much harder. 3DS2 reduces online payment fraud by up to 70%, according to industry data from major payment processors. The US lags behind on 3DS adoption, but the trend is clearly toward more authentication, not less.

That said, the practical defences are the same regardless of whether the account is fake or the card is stolen:

Stripe Radar scores every payment attempt using machine learning trained on billions of transactions. It reduces fraud by 38% on average for merchants who use it. In early 2026, Stripe added a dedicated free trial abuse model that predicts abusive behaviour with 90% accuracy. If you're running an AI product with a free tier, this is worth enabling.

// Stripe Radar rule examples (set in Dashboard or via API)
// Block if Radar risk score is elevated:
::riskLevel:: = 'elevated'  → Block

// Block disposable email domains:
::emailDomain:: IN ('tempmail.com', 'guerrillamail.com')  → Block

// Require 3D Secure for first-time customers:
::isNewCustomer:: AND ::amount:: > 5000  → Request 3D Secure

3D Secure (3DS) adds cardholder verification before the charge processes. For AI products, requiring 3DS on the first payment or on any payment above a threshold reduces fraud from stolen cards. In Europe, SCA makes this mandatory for most transactions anyway. In the US, it's optional but increasingly worthwhile, especially at higher price points.

Always require a valid payment method before granting access to any tier, including free. A card-on-file requirement with a $0 authorization filters out the majority of throwaway accounts. Stripe's SetupIntents API handles this cleanly.

Device fingerprinting catches what card checks miss. Stripe Radar includes its own device fingerprinting at the payment layer, so it can spot repeat fraudsters when they try to pay. But if you offer a free tier or trial where no payment happens at signup, Radar never sees the user. For that, you need a standalone tool like Fingerprint (formerly FingerprintJS), which generates a visitor ID based on browser and device attributes at registration time. If the same device creates a third account, flag or block it.

// Fingerprint integration example
const visitorId = req.body.visitor_id; // from Fingerprint JS agent

const previousAccounts = await db.query(
  'SELECT COUNT(*) FROM signups WHERE fingerprint = $1',
  [visitorId]
);

if (previousAccounts.count >= 2) {
  return res.status(403).json({
    error: "Account limit reached for this device"
  });
}

Velocity checks round this out: flag patterns like multiple signups from the same IP range, identical billing addresses, or rapid sequential account creation. These can be Stripe Radar rules or logic in your own signup flow.


What happens when customers use now and pay later?

This is the risk specific to post-paid metered billing. The customer uses your product throughout the billing period. Stripe meters every event. At cycle end, Stripe generates an invoice and attempts to charge the card on file.

If the payment fails, you have already incurred the infrastructure costs. For AI products with high per-request costs, this gap between usage and collection can get expensive quickly.

A customer generates 20,000 images at $0.05 each over 30 days. That's $1,000 in compute costs you've already paid to your GPU provider. The end-of-month invoice fails. You have a $1,000 loss and a collections problem.

Partial fix: Stripe billing thresholds

Stripe offers billing thresholds that trigger an invoice mid-cycle when usage exceeds a set amount. This shortens the gap between usage and payment.

const subscription = await stripe.subscriptions.create({
  customer: customer.id,
  items: [{ price: meteredPriceId }],
  billing_thresholds: {
    amount_gte: 5000, // Invoice when usage hits $50.00
  },
});
// Now Stripe generates an interim invoice at $50
// instead of waiting for the full billing cycle.

This helps, but it doesn't eliminate the risk. Usage between threshold triggers is still unbilled. And if the threshold invoice itself fails, the customer continues generating usage until you detect and suspend them.

Structural fix: collect payment before usage

The architectural solution is to collect payment before usage happens. Instead of metering now and invoicing later, the customer funds a balance upfront. Each usage event debits the balance in real time. When the balance reaches zero, usage stops automatically.

This is the model used by OpenAI, Anthropic, and Replicate. It isn't something Stripe Billing supports natively. Stripe's credit grants apply at invoice finalization, not at event time. To build prepaid balance gating on Stripe, you'd need to maintain a balance ledger in your own database, check it before every API request, deduct on each usage event, and reconcile with Stripe's invoicing separately. It's doable, but it amounts to building your own billing system on top of Stripe's.


How do leaked API keys cause runaway costs?

When a customer's API key is compromised, the attacker generates usage on the customer's account. The customer didn't authorize the usage, but the billing system doesn't know the difference. The result is a disputed invoice or a chargeback.

Rate limiting is the first defence. Cap requests per minute, per hour, and per day at the API gateway level. Stripe doesn't handle this; it lives in your application layer.

// Example: express-rate-limit for API endpoints
const rateLimit = require('express-rate-limit');

const apiLimiter = rateLimit({
  windowMs: 60 * 1000,     // 1 minute
  max: 100,                 // 100 requests per minute
  keyGenerator: (req) => req.headers['x-api-key'],
  handler: (req, res) => {
    res.status(429).json({
      error: "Rate limit exceeded",
      retry_after: 60,
    });
  },
});
app.use('/api/generate', apiLimiter);

Usage alerts notify both you and the customer when spending crosses thresholds. Stripe provides usage record summaries you can poll, but real-time alerting requires your own implementation.

If the account runs on a prepaid balance, a leaked key can only burn through what's left. Once the balance hits zero, all requests stop. The blast radius is capped by design, without any custom detection logic. This matters most for products implementing consumption-based pricing where individual requests are expensive.


How many protection layers do you need?

Not every AI product needs every layer. The right stack depends on how much a single request costs you.

Under $0.01 per request (low risk): Stripe Radar + 3DS + rate limits. Post-paid billing works fine here.

$0.01 to $0.10 per request (medium risk): Add billing thresholds and usage alerts. You want to shorten the collection gap.

$0.10 to $1.00 per request (high risk): Add prepaid balances or hard spending caps. At this level, the billing model itself needs to enforce limits.

Over $1.00 per request (critical risk): Prepaid balances become mandatory. You need real-time balance gating that rejects requests before they incur costs you can't recover.

The general pattern: the more expensive each request, the more the billing system needs to act as a circuit breaker. At the low end, Stripe's native tools handle it. At the high end, you need real-time control that lives between the API call and the compute.

For teams evaluating their options, the comparison of billing software in 2026 covers the landscape beyond Stripe.


How Credyt handles these risks differently

Credyt is real-time monetization infrastructure for AI products. The core difference from Stripe's metered billing: usage is authorized and billed in real time rather than accumulated and invoiced at cycle end.

Before executing an expensive operation, your application checks the customer's balance via Credyt's API. If there's enough credit, you allow the request through. If the balance is too low, you can reject the operation before any cost is incurred. The decision stays in your code; Credyt gives you the real-time balance to make it. Customers fund their wallets upfront, so a failed card simply means a wallet that doesn't get topped up, not an unpaid invoice.

const { available } = await (await fetch(
  `https://api.credyt.ai/customers/${credytId}/wallet/default:USD`,
  { headers }
)).json();

if (available < 1.00) {
  // Not enough balance — reject before incurring compute costs
  return res.status(402).json({ error: "Insufficient balance" });
}
// Balance is sufficient — proceed with the expensive GPU operation

You can define your own billing units (tokens, credits, GPU-hours) with exchange rates to USD, and adjust the rate when infrastructure costs shift without changing customer-facing prices. Stripe has no native equivalent.

If an API key leaks, the damage stops when the balance hits zero. No custom anomaly detection needed.

For early-stage teams, this matters because Metronome (now part of Stripe) targets enterprise contracts, and native Stripe Billing requires you to build wallet logic yourself. Credyt provides real-time billing without the engineering investment or enterprise pricing.

Explore the docs

Don't let monetization slow you down.

Free to start. Live in hours. No engineering team required.