Розробка системи білінгу Node-as-a-Service

Правильний облік споживання ресурсів — ключ до прибутковості NaaS-платформи, але без точного білінгу легко втратити дохід і довіру клієнтів. Ми розробляємо системи білінгу Node-as-a-Service, які враховують Compute Units, тарифи та crypto-платежі, автоматизуючи весь цикл — від збору метрик до виставлення рахунків. Наша команда реалізує проєкт під ключ із подальшою підтримкою, забезпечуючи прозорість і надійність розрахунків.
Часті запитання

Запустити ноду нескладно. Складно правильно рахувати гроші — особливо коли unit of consumption — це не запит, а час роботи ноди, тип мережі, версія клієнта та тариф, який вибрав користувач три тижні тому. NaaS білінг провалено в більшості молодих провайдерів не тому що задача технічно важка, а тому що між «рахувати гроші приблизно вірно» та «рахувати гроші точно та прозоро» — прірва в кілька місяців інженерної роботи. Ми розробляємо системи білінгу для NaaS вже багато років і знаємо, як уникнути типових помилок. За цей час реалізували понад 20 проєктів, від простих MVP до повноцінних crypto-native платформ. У цій статті розберемо архітектуру, з якою не соромно виходити в production, моделі тарифікації, які обирають зрілі провайдери, та підводні камені, які ламають білінг у продакшені. Ви дізнаєтесь, як побудувати шар збору метрик без втрати даних, налаштувати rating engine на PostgreSQL та інтегрувати crypto-платежі в USDC. Також розповімо, які проблеми виникають із clock skew та duplicate events, і як їх вирішити.

Які моделі тарифікації використовуються в NaaS?

Pay-per-request — класика для RPC провайдерів (Alchemy, Infura, QuickNode). Рахуємо кількість JSON-RPC викликів, з ваговими коефіцієнтами за методами:

Метод Compute Units
eth_blockNumber 10
eth_getBalance 19
eth_call 26
eth_getLogs 75
trace_transaction 150
debug_traceTransaction 500

eth_getLogs із широким діапазоном блоків — це атака на ноду. Без вагових коефіцієнтів користувач може зробити один запит вартістю тисяч «звичайних». Alchemy називає це Compute Units, QuickNode — Credits. Назви різні, сенс один.

Time-based (subscription) — виділена нода фіксованої потужності оплачується помісячно. Зрозуміліше для користувача, передбачуваний revenue для провайдера. Мінус: користувач переплачує при низькому навантаженні.

Hybrid — базовий план із місячним включеним обсягом, overage billing зверху. Використовують більшість зрілих провайдерів.

Модель Переваги Недоліки
Pay-per-request Точно платиш за використання, легко масштабується Непередбачуваний рахунок, складність rate limiting
Time-based (subscription) Передбачуваний дохід, простота для користувача Переплата при низькому навантаженні
Hybrid Баланс гнучкості та передбачуваності Складність реалізації overage billing

Як влаштована архітектура білінгової системи?

Як організувати шар збору метрик? — розробка системи білінгу

Критичний шлях: кожен RPC запит має бути залогований до відповіді користувачу — інакше при краші втрачаємо дані про використання. Допустимий відсоток втрат (sampling loss) — менше 0.01%. Якщо втрачаємо більше — backpressure або нода помирає під навантаженням.

Архітектура:

Client Request ↓ API Gateway (Nginx / Envoy / Kong) ↓ [access log + request metadata] Billing Proxy (sidecar) — async write to queue ↓ RPC Node Cluster ↓ Response → Client 

Billing proxy пише до Apache Kafka або NATS JetStream — обидва дають at-least-once delivery. Синхронний запис до бази на кожен запит вбиває latency (ми додаємо 100–500 мс до кожного RPC виклику, що неприпустимо). Використання черги дозволяє обробляти події в 10 разів швидше порівняно з прямим записом у БД.

// Async metric emission — не блокує запит
func (b *BillingMiddleware) RecordUsage(ctx context.Context, event UsageEvent) {
	select {
	case b.eventChan <- event:
		// успішно поставлено в буфер
	default:
		// буфер повний — метрика втрачена, логуємо як sampling loss
		b.metrics.IncSamplingLoss()
	}
}

Агрегація та rating engine

Raw події з Kafka → rating pipeline → billable records у PostgreSQL. Rating — це застосування тарифних правил до raw usage. Для NaaS:

class RatingEngine:
    def rate_event(self, event: UsageEvent, plan: Plan) -> Decimal:
        method_weight = self.compute_unit_table.get(
            event.method, DEFAULT_WEIGHT
        )
        # Застосовуємо тарифний план
        if plan.type == "included_pool":
            remaining = plan.included_units - plan.used_units
            if remaining > 0:
                billable = max(0, method_weight - remaining)
                plan.used_units += method_weight
            else:
                billable = method_weight
        elif plan.type == "pay_per_use":
            billable = method_weight
        return Decimal(billable) * plan.unit_price

Агрегація відбувається по часових вікнах (5-хвилинні buckets), фінальний запис — в кінці розрахункового періоду. Це створює billing lag — користувач витратив гроші, але бачить оновлення балансу через 5 хвилин. Це норма для NaaS.

Зберігання даних

Для білінгу PostgreSQL — правильний вибір. Не ClickHouse, не MongoDB. Білінг вимагає ACID при списанні коштів. Схема:

-- Immutable usage log
CREATE TABLE usage_events (
    id BIGSERIAL PRIMARY KEY,
    account_id UUID NOT NULL,
    node_id UUID NOT NULL,
    method VARCHAR(64),
    chain_id INTEGER,
    weight INTEGER,
    occurred_at TIMESTAMPTZ NOT NULL,
    billed_at TIMESTAMPTZ
) PARTITION BY RANGE (occurred_at);

-- Billing periods
CREATE TABLE billing_records (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    account_id UUID NOT NULL,
    period_start TIMESTAMPTZ NOT NULL,
    period_end TIMESTAMPTZ NOT NULL,
    total_units BIGINT,
    total_amount NUMERIC(20, 8),
    currency VARCHAR(10), -- 'USD', 'USDC', 'ETH'
    status VARCHAR(20), -- 'pending', 'invoiced', 'paid', 'overdue'
    created_at TIMESTAMPTZ DEFAULT NOW()
);

usage_events партиціонується за датою — інакше через рік таблиця перестане вміщатися в індекси оперативної пам'яті. Retention policy: raw events зберігаються 90 днів, агрегати — безстроково.

Як реалізувати crypto-native білінг?

Prepaid баланс у стейблкоїнах

Більшість NaaS для Web3 працюють у prepaid моделі: користувач поповнює баланс в USDC/USDT, списання відбувається з нього. Це простіше ніж підписка через кредитну картку і немає chargeback ризиків.

contract NaaSBilling {
    IERC20 public immutable usdc;
    mapping(address => uint256) public balances;
    address public billingOracle; // multisig or oracle service

    event Deposit(address indexed account, uint256 amount);
    event Deduction(address indexed account, uint256 amount, string invoiceId);

    function deposit(uint256 amount) external {
        usdc.transferFrom(msg.sender, address(this), amount);
        balances[msg.sender] += amount;
        emit Deposit(msg.sender, amount);
    }

    // Тільки billingOracle може списувати
    function deductBalance(
        address account,
        uint256 amount,
        string calldata invoiceId
    ) external onlyBillingOracle {
        require(balances[account] >= amount, "Insufficient balance");
        balances[account] -= amount;
        emit Deduction(account, amount, invoiceId);
    }
}

Важливий паттерн: billingOracle — не EOA, а multisig або сервіс з HSM. Ключ від оракула компрометується → всі баланси під загрозою.

Автоматичне поповнення

Low balance triggers — користувач налаштовує автопоповнення при досягненні порогу: threshold, refillAmount, sourceWallet, maxMonthlySpend. maxMonthlySpend — обов'язковий захист від billing runaway. Без нього баглий клієнт робить мільйон запитів і з'їдає весь баланс користувача за годину.

Які алерти та rate limiting потрібні?

Rate limiting на рівні API Gateway (не білінгу): 1000 req/sec per API key — стандартний дефолт. Без rate limiting один користувач з багом може покласти ноду для всіх.

Billing alerts — нотифікації при:

  • Баланс впав нижче X% від звичайної місячної витрати (наприклад, 80%)
  • Різкий spike usage (>3x середнього за останню годину)
  • Нода недоступна (клієнт платить за downtime — це має компенсуватися SLA кредитами)

SLA credits — автоматичне нарахування кредитів при downtime. Рахується через uptime probe (зовнішній сервіс моніторингу, не ваш власний). Self-reported uptime 99.99% не викликає довіри у корпоративних клієнтів.

Які проблеми білінгу зустрічаються в production?

За час роботи з NaaS білінгом зустрічали кілька нетривіальних проблем. Розглянемо три найбільш критичні.

Clock skew між нодами — якщо billing proxy та нода мають розбіжність годинників >1 сек, timestamps у usage events некоректні. NTP обов'язковий, бажано chrony з Google NTP серверами.

Duplicate events при retry — Kafka at-least-once delivery означає дублікати при retry. Кожна подія повинна мати idempotency key (request_id + node_id), rating engine де-дуплікує перед записом.

Timezone bugs у billing cycles — розрахунковий період «1-е число місяця» в UTC. Користувач з UTC-8 бачить що цикл закривається о 16:00 його часу. Потрібна явна документація і за бажанням — кастомні billing cycles.

Терміни розробки повноцінної NaaS billing системи: 3–5 місяців для команди з 2–3 backend інженерів. MVP з prepaid балансом та базовим rate limiting — 6–8 тижнів.

Що входить у розробку системи білінгу?

  • Документація архітектури та API
  • Вихідний код з коментарями
  • Інструкція з розгортання (Docker, Kubernetes)
  • Навчання команди замовника
  • Технічна підтримка 3 місяці
  • Гарантія усунення помилок

Гарантія точності білінгу: ми гарантуємо, що система проходить аудит на предмет витоку коштів та коректності розрахунків. Протягом 3 місяців після здачі виправляємо будь-які помилки безкоштовно. Помилки білінгу можуть коштувати до 10% виручки провайдера — наше завдання звести цей ризик до нуля.

Зв'яжіться з нами для консультації з архітектури вашого NaaS білінгу. Замовте розробку системи під ключ та отримайте оцінку проекту.

Напрямки блокчейн-розробки

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    816
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1142