Usage Metering and Billing

1. v0.1 commercial model

Use participant-minute as the primary billable unit.

Example:

Participant A: 30 minutes
Participant B: 30 minutes

Total: 60 participant-minutes

This is independent of the customer's business price for a consultation.

2. Internal precision

Store usage in seconds.

Display and price using a configurable billing rule.

Example initial policy:

raw duration        second precision
billing aggregation project-level
commercial display  participant-minutes

Whether to round each session or total monthly usage should be a plan setting, not embedded in event handlers.

3. Technical metrics

Store technical usage separately even if v0.1 has one simple commercial price:

participant_seconds
audio_seconds
video_seconds
screen_share_seconds
bytes_in
bytes_out
region
media_node
TURN usage where measurable

This allows future plans such as audio-only, HD, recording, or bandwidth-based pricing without losing historical data.

4. Source of truth

Billing is derived from finalized participant sessions, not directly from customer webhooks.

Pipeline:

Media engine event
      |
      v
raw event store
      |
      v
participant session reconciliation
      |
      v
usage record finalized
      |
      v
pricing
      |
      v
usage charge
      |
      v
wallet ledger

5. Event reconciliation

Workers must handle:

  • duplicated joined event
  • duplicated left event
  • missing left event
  • reconnect
  • service restart
  • out-of-order event
  • room force-close
  • media-node failure

Each active session has last_seen_at.

A reconciler periodically checks media-engine state and closes stale sessions according to policy.

6. Reconnect grace period

A short disconnect should not create confusing billing gaps.

Suggested configurable concept:

reconnect_grace_seconds

Example behavior:

  • participant loses network
  • reconnects within grace period
  • same logical participant session remains billable according to project policy

The exact policy should be explicit and documented to customers.

7. Plans and prices

Do not hard-code the per-minute price in code (the default is 0.00699 USD per participant-minute, i.e. $6.99 per 1,000).

Use data:

plan
metric
unit_size
unit_price
currency
effective_from

Possible beta plan:

Metric: participant_minute
Price: configurable
Currency: USD

A public launch price is a commercial decision after capacity/load testing.

8. Prepaid first

v0.1 uses prepaid credit.

Advantages:

  • simple risk model
  • no collection process
  • easy beta onboarding
  • immediate quota enforcement
  • suitable for small teams and startups

Flow:

top-up
  |
wallet credit
  |
RTC usage
  |
usage charge
  |
wallet debit

Online top-ups (Stripe Checkout, POST /v1/billing/topups) accept 5.00 to 10,000.00 USD per payment. The maximum is a product limit, well under Stripe's own Checkout ceiling (999,999.99 USD); larger prepayments are invoiced and credited by an operator (make prod-credit).

A top-up whose Stripe session was never created (the Stripe call failed or timed out) stays creating with no provider reference. The payment reconciler marks it expired with failure_code provider_session_not_created after 25 hours, past Stripe's 24-hour Checkout expiry, and emits payment.expired like any other expiry. If a session did exist and is paid anyway, the Stripe webhook still credits it.

9. Wallet ledger

Every money mutation creates an immutable ledger row.

Example:

+1000.00  topup
-6.00     usage_charge
+6.00     refund
-50.00    adjustment_debit

Never rewrite history.

A correction creates a compensating entry.

10. Balance checks and session grace

The Beta policy is implemented as:

  • room creation does not reserve or debit credit
  • participant creation requires balance >= minimum_credit_to_start
  • /v1/connect re-checks the same credit gate
  • an already-active call is never terminated just because balance reaches zero
  • finalized usage is always charged, even when the resulting balance becomes negative
  • a negative/exhausted balance blocks the next participant/connect until credit is restored

This avoids losing billable usage while also avoiding an unexpected mid-consultation disconnect.

Project-configurable fields:

participant_minute_price
low_credit_threshold
minimum_credit_to_start

Credit state:

normal
low
exhausted

Transitions emit:

credit.low
credit.exhausted
credit.restored

11. Reservations

v0.1 does not require wallet reservation for every room.

Later, projects may optionally reserve estimated maximum usage before allowing a session.

Keep schema flexible for:

reserved_balance
reservation
reservation_release

12. Charge idempotency

Each finalized usage record can be charged once.

Database unique constraint:

usage_record_id

Charging transaction:

  1. lock wallet/account row
  2. ensure usage record has no charge
  3. take the price, currency and billing_enabled snapshotted on the usage record (records with billing disabled are waived and never charged)
  4. calculate decimal amount
  5. debit wallet (session-grace settlement may make balance negative)
  6. insert usage_charge
  7. insert immutable wallet ledger debit
  8. update credit state and queue any credit webhook event
  9. commit

All inside one database transaction.

13. Pricing precision

Use decimal arithmetic.

Never use binary floating point for USD balances.

Recommended concepts:

NUMERIC for money
integer seconds for usage
UTC timestamps

14. Refunds

Refund references the original charge.

Reasons:

service_incident
duplicate_charge
manual_support
billing_correction

Refund is a new ledger credit.

15. Free credit

Beta onboarding can grant promotional credit.

Use:

type=adjustment_credit
metadata.reason=beta_signup

Do not special-case promotional money outside the ledger.

16. Usage dashboard

Show:

  • today participant-minutes
  • current month participant-minutes
  • audio/video split
  • rooms
  • estimated charge
  • current balance
  • low-credit status
  • daily chart

17. Billing API guarantees

Usage dashboards may be near-real-time.

Ledger/balance is authoritative.

Clearly distinguish:

estimated usage
finalized usage
charged usage

18. Commercial metrics to watch

Before finalizing public price:

  • actual bandwidth per 1,000 participant-minutes
  • TURN percentage
  • average bitrate
  • CPU per concurrent participant
  • peak concurrent rooms
  • support overhead
  • payment gateway fee
  • backup/monitoring cost
  • spare capacity target
  • hardware/network amortization
  • VAT/tax treatment

19. Future billing dimensions

Schema should permit:

audio participant-minute
SD video participant-minute
HD video participant-minute
FHD video participant-minute
screen-share minute
recording minute
recording storage GB-month
streaming egress GB
SIP minute
premium support
dedicated region

Do not implement these in v0.1.