Skip to content

Features

UsageMeter aggregate

IUsageMeter / UsageMeterEntity, one per (TenantId, Dimension). Fields: UsageMeterId, TenantId, Dimension, CounterValue (long), QuotaLimit (nullable), ThresholdWarningPercent (default 80), ThresholdCrossedEmitted, QuotaExceededEmitted, Description, AggregateVersion, timestamps.

Quota lifecycle

RecordUsageAsync adds Delta to CounterValue, then PrepareQuotaTransitions compares against QuotaLimit and ThresholdWarningPercent:

  • Emits QuotaThresholdCrossedIntegrationEvent once when crossing the warn level (below quota).
  • Emits QuotaExceededIntegrationEvent once when CounterValue >= QuotaLimit.

RollUsageCounterAsync resets CounterValue = 0 and clears the emission flags - a billing-period roll, not retention.

Published events

Event Topic
UsageRecordedIntegrationEvent metering.usage.v1.usage-recorded
CounterRolledIntegrationEvent metering.counters.v1.counter-rolled
QuotaThresholdCrossedIntegrationEvent metering.quota.v1.quota-threshold-crossed
QuotaExceededIntegrationEvent metering.quota.v1.quota-exceeded

Inbound sagas

Inbound event Topic Saga -> action
TenantActivatedMeteringInboundEvent tenants.domain.v1.tenant-activated TenantActivationMeteringProvisioningStateMachine -> ProvisionBaselineMetersAsync
SubscriptionCreatedMeteringInboundEvent billing.subscriptions.v1.subscription-created SubscriptionCreatedMeteringProvisioningStateMachine -> ProvisionSubscriptionMeterAsync
EntitlementsChangedQuotaInboundEvent entitlements.v1.effective-entitlements-updated EntitlementsChangedQuotaStateMachine -> ApplyUsageQuotaAsync

Baseline dimensions provisioned on tenant activation: api.requests, storage.gb.

Unwired saga

UsageMeterQuotaEnforcementStateMachine exists but its UsageReportedForQuotaInboundEvent topic is not wired in MeteringMassTransitTopology.ConfigureInboundConsumedMessageTopology (documented in docs/backlog/metering-gap-backlog.md).

Orleans

UsageMeterGrain keyed {tenantId}:{dimension} (UsageMeterGrainKey.Format/Parse) - RecordUsage, RollCounter, EnsureProvisioned, ApplyQuota, GetSnapshot.

See also