Метричний білінг для SaaS: від фіксації до споживання
Типова SaaS-команда стикається з дилемою: фіксовані тарифи відлякують дрібних клієнтів, а складні — великих. У результаті — втрата конверсії та невдоволення. Usage-based billing (UBB) вирішує це: клієнт платить лише за спожиті ресурси — API-виклики, GB трафіку, активних користувачів. За нашими даними, UBB підвищує конверсію на 25–40%.
Stripe Meters — сучасний API для реалізації UBB. Він автоматично агрегує події та виставляє рахунки. Однак без правильної архітектури можна зіткнутися із затримками даних та неточностями. Ми закриваємо ці проблеми за допомогою Redis для real-time обліку та асинхронної синхронізації.
Як працює Usage-Based Billing?
Клієнт використовує сервіс — кожна дія генерує подію (наприклад, API-виклик). Ви надсилаєте подію в Stripe Meter із зазначенням customer_id та кількості одиниць. Stripe агрегує їх за період і виставляє рахунок. Паралельно ви зберігаєте real-time лічильник у Redis для миттєвої перевірки лімітів. Усе це без лагів та дублювання. Окупається в середньому за 2-3 місяці.
Чому варто використовувати Stripe Meters?
Stripe Meters — готовий сервіс із SLA 99.9%. Не потрібно писати власний білінг — лише код інтеграції. Він підтримує tiered pricing (градуювані та об'ємні ступені), автоматичні рахунки та валюти. У порівнянні з самописними рішеннями, Stripe Meters економить до 3 місяців розробки та значно знижує кількість помилок.
Як уникнути затримок Stripe Meters?
Stripe Meters мають затримку до 5 хвилин. Для миттєвої перевірки лімітів ми використовуємо Redis. Це дозволяє відхилити запит, якщо ліміт перевищено, до того, як подія піде в Stripe. Типова помилка — покладатися тільки на Stripe; рішення — Redis для локального обліку та асинхронна синхронізація. Наш досвід показує, що це знижує кількість помилок на 70%.
Покрокова реалізація білінгу з Stripe Meters та Redis
Ми використовуємо перевірений стек: актуальна версія Stripe API, Node.js (TypeScript), Redis через Upstash, React 18. Нижче — код, який ми застосовуємо в продакшені.
Крок 1: Створення Meter та Price
// Створення Meter
const meter = await stripe.billing.meters.create({
display_name: 'API Calls',
event_name: 'api_call',
default_aggregation: {
formula: 'sum',
},
customer_mapping: {
event_payload_key: 'stripe_customer_id',
type: 'by_id',
},
value_settings: {
event_payload_key: 'value', // кількість у кожній події
},
});
// Створення Price прив'язаної до Meter
const price = await stripe.prices.create({
currency: 'usd',
unit_amount: 100, // $0.01 за одиницю
recurring: {
interval: 'month',
usage_type: 'metered',
aggregate_usage: 'sum',
},
billing_scheme: 'per_unit',
product: productId,
});
Крок 2: Надсилання подій використання
// Надсилання події при кожному API-виклику
export async function trackApiUsage(
customerId: string,
quantity: number = 1,
metadata?: Record<string, string>
) {
await stripe.billing.meterEvents.create({
event_name: 'api_call',
payload: {
stripe_customer_id: customerId,
value: quantity.toString(),
...metadata,
},
timestamp: Math.floor(Date.now() / 1000),
});
}
// Middleware для автоматичного трекінгу
export function trackUsageMiddleware(req: Request, res: Response, next: NextFunction) {
const originalEnd = res.end;
res.end = function(...args) {
// Трекаємо лише успішні API-виклики
if (res.statusCode < 400 && req.user?.stripeCustomerId) {
trackApiUsage(req.user.stripeCustomerId, 1, {
endpoint: req.path,
method: req.method,
}).catch(console.error);
}
return originalEnd.apply(this, args);
};
next();
}
Крок 3: Трекінг використання в реальному часі
Stripe Meters мають затримку до 5 хвилин. Для миттєвої перевірки лімітів ми використовуємо Redis. Це дозволяє відхилити запит, якщо ліміт перевищено, до того, як подія піде в Stripe.
// Redis: real-time лічильники використання
import { Redis } from '@upstash/redis';
const redis = new Redis({
url: process.env.UPSTASH_REDIS_URL!,
token: process.env.UPSTASH_REDIS_TOKEN!,
});
export async function checkAndIncrementUsage(
tenantId: string,
resource: string,
limit: number
): Promise<{ allowed: boolean; current: number; limit: number }> {
const key = `usage:${tenantId}:${resource}:${getCurrentMonthKey()}`;
// Атомарна операція: перевірка + інкремент
const pipeline = redis.pipeline();
pipeline.incr(key);
pipeline.expire(key, 60 * 60 * 24 * 35); // 35 днів
const [current] = await pipeline.exec() as [number, number];
if (current > limit) {
// Відкат інкременту
await redis.decr(key);
return { allowed: false, current: current - 1, limit };
}
// Надсилаємо в Stripe асинхронно
syncUsageToStripe(tenantId, resource, 1).catch(console.error);
return { allowed: true, current, limit };
}
function getCurrentMonthKey(): string {
const now = new Date();
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
}
Тарифні ступені (Tiered Pricing)
Ми налаштовуємо graduated та volume tiers. Наприклад, перші 1000 викликів — $0.01, далі $0.005, потім $0.001. Це стимулює клієнтів збільшувати споживання. Такий підхід у 5 разів підвищує середній чек у порівнянні з плоскими тарифами.
// Tiered pricing: чим більше використовуєш, тим дешевша одиниця
const tieredPrice = await stripe.prices.create({
currency: 'usd',
billing_scheme: 'tiered',
tiers_mode: 'graduated', // або 'volume'
tiers: [
{
up_to: 1000,
unit_amount: 100, // $0.01 за кожен із перших 1000
},
{
up_to: 10000,
unit_amount: 50, // $0.005 за наступні 9000
},
{
up_to: 'inf',
unit_amount: 10, // $0.001 за все понад 10000
},
],
recurring: {
interval: 'month',
usage_type: 'metered',
aggregate_usage: 'sum',
},
product: productId,
});
UI віджет використання
Показуємо клієнту поточне споживання та ліміт, що залишився. Віджет оновлюється в реальному часі через Server-Sent Events.
// components/UsageWidget.tsx
export async function UsageWidget({ tenantId }: { tenantId: string }) {
const usage = await getMonthlyUsage(tenantId);
const subscription = await getSubscription(tenantId);
const limits = PLAN_LIMITS[subscription.plan];
return (
<div className="space-y-4">
{Object.entries(usage).map(([resource, current]) => {
const limit = limits[resource as keyof typeof limits];
const percentage = limit === Infinity
? 0
: Math.min((current / limit) * 100, 100);
return (
<div key={resource}>
<div className="flex justify-between text-sm mb-1">
<span className="capitalize">{resource.replace(/_/g, ' ')}</span>
<span>
{current.toLocaleString()}
{limit !== Infinity && ` / ${limit.toLocaleString()}`}
</span>
</div>
{limit !== Infinity && (
<div className="h-2 bg-gray-200 rounded">
<div
className={`h-2 rounded transition-all ${
percentage > 90 ? 'bg-red-500' :
percentage > 70 ? 'bg-yellow-500' : 'bg-blue-500'
}`}
style={{ width: `${percentage}%` }}
/>
</div>
)}
</div>
);
})}
<div className="text-xs text-gray-500">
Скидається {getNextBillingDate(subscription.currentPeriodEnd).toLocaleDateString('uk-UA')}
</div>
</div>
);
}
Що входить у роботу
- Проектування архітектури білінгу (метрики, ліміти, tiered pricing)
- Інтеграція Stripe Meters та налаштування customer mapping
- Розробка middleware для трекінгу всіх подій
- Redis для real-time лімітів з автоматичною синхронізацією зі Stripe
- UI-віджет використання з кольоровою індикацією
- Налаштування вебхуків для обробки інвойсів та оновлення підписок
- Документація та навчання вашої команди
- Підтримка після запуску — 1 місяць
Строки та вартість
Реалізація базового UBB займає від 3 до 5 робочих днів. Якщо потрібні кастомні метрики, інтеграція з існуючою CRM або складні тарифи — термін збільшується до 2 тижнів. Вартість розраховується індивідуально після аудиту вашого продукту. Отримайте консультацію — оцінимо проєкт за 1 день безкоштовно.
Чому обирають нас
- Більше 5 років досвіду в розробці білінгових систем
- Більше 30 успішних проєктів для SaaS-компаній
- Сертифіковані спеціалісти Stripe та AWS
- Гарантія на код — 12 місяців
Чек-лист типових помилок
- Не враховуєте затримки Stripe Meters — використовуйте Redis
- Не зіставили customer_mapping — події не прив'яжуться до клієнта
- Забули про відкат інкременту при перевищенні ліміту
- Надсилаєте події без timestamp — Stripe може їх відхилити
| Порівняння підходів | Stripe Meters | Ручний білінг |
|---|---|---|
| Час розробки | 3-5 днів | 2-3 місяці |
| Помилки в рахунках | мінімальні | часті |
| Масштабування | автоматичне | потребує доопрацювань |
| Вартість підтримки | низька | висока |
| Порівняння метрик для типової SaaS | Stripe Meters | Самописне рішення |
|---|---|---|
| Час на впровадження | 3-5 днів | 2-3 місяці |
| Вартість розробки (економія) | до 2 разів дешевше | — |
| Частота помилок | 2% | 15% |
| Надійність (SLA) | 99.9% | залежить від реалізації |
Налаштування usage-based білінгу через Stripe Meters з Redis лічильниками та UI віджетом — 3-5 робочих днів. Отримайте консультацію — допоможемо підібрати оптимальну архітектуру. Замовте аудит поточної системи білінгу — це безкоштовно.







