Correctness guarantees

This feature is currently in Beta and should not be used in a production environment.

Metering & Billing keeps credit balances correct by booking every credit movement on an internal double-entry ledger. The public credit balance is not a mutable counter. It’s derived from ledger movements that are balanced, ordered, and preserved over time.

This matters for customers and operators because the same rules explain every balance change:

  • Grants add credits.
  • Charges consume credits.
  • Expiration removes unused credits.
  • Corrections add follow-up movements instead of changing the past.
  • Transaction history shows the customer-facing result of those movements.

Double-entry ledger

Every credit movement is backed by balanced ledger entries. When credits move into or out of a customer balance, Metering & Billing records the matching side of the movement in another account.

At a high level, the credit ledger contains customer accounts and business accounts:

 
flowchart LR
  subgraph Customer["Customer accounts"]
    FBO["Customer credit balance"]
    REC["Customer receivable"]
    ACC["Customer accrued"]
  end

  subgraph Business["Business accounts"]
    WASH["Settlement boundary"]
    EARN["Earnings"]
    BRK["Expiration / breakage"]
  end

  REC --> FBO
  FBO --> ACC
  ACC --> EARN
  FBO --> BRK
  WASH --> REC
  

The customer credit balance is the customer-facing account. Receivable and accrued accounts exist so Metering & Billing can represent payment state, consumed usage, and recognition separately. Business accounts represent the other side of settlement, earnings, and expiration.

Movements

A settled balance is calculated from committed credit movements. If a customer receives 100 credits and uses 30, the settled balance is 70.

+100 funded
 -30 consumed
----
  70 settled balance

Because the balance comes from movements, Metering & Billing can also answer point-in-time balance questions. A balance read before an expiration doesn’t include that expiration, while a balance read at or after the expiration does.

Movement immutability

Credit history is immutable. When usage changes, a charge is canceled, or a billing workflow reverses previously consumed credits, Metering & Billing books a correction movement. Metering & Billing doesn’t rewrite the original movement.

This gives transaction history a stable audit shape:

T1: +100 funded
T2:  -40 consumed
T3:  +10 correction

The customer can still see that 40 credits were consumed at T2. The later correction explains why 10 credits returned at T3.

Deterministic consumption

When a customer has multiple grants in the same currency, Metering & Billing consumes credits in a deterministic order:

priority asc
expires_at asc
stable movement order asc

Lower priority values are consumed first. For equal priority, earlier-expiring credits are consumed first. If both are equal, Metering & Billing uses stable movement order.

This rule keeps consumption predictable and also protects expiration correctness. When credits are consumed, Metering & Billing knows which future expiration should be reduced.

Credit expiration

Expiration removes only unused credits. If a customer uses part of an expiring grant, the used portion doesn’t expire later.

T1:  +100 funded, expires at T10
T5:   -30 consumed
T10:  -70 expired

The original grant was 100 credits, but only 70 credits remained unused at expiration. The consumed 30 credits were already spent, so they are not expired.

Transaction history is a projection

The double-entry ledger contains the accounting detail needed for correctness. Customer credit transaction history shows the customer-facing movement:

Type

Meaning

funded credits were added
consumed credits were used by charges
expired unused credits expired

This projection keeps the public history understandable while preserving accounting correctness underneath.

Help us make these docs great!

Kong Developer docs are open source. If you find these useful and want to make them better, contribute today!