Marketplace
usage-metering
Usage tracking, metering infrastructure, aggregation patterns, and consumption-based billing support for SaaS applications
allowed_tools: Read, Glob, Grep, Task, mcp__perplexity__search, mcp__microsoft-learn__microsoft_docs_search, mcp__context7__query-docs
$ Instalar
git clone https://github.com/melodic-software/claude-code-plugins /tmp/claude-code-plugins && cp -r /tmp/claude-code-plugins/plugins/saas-patterns/skills/usage-metering ~/.claude/skills/claude-code-plugins// tip: Run this command in your terminal to install the skill
SKILL.md
name: usage-metering description: Usage tracking, metering infrastructure, aggregation patterns, and consumption-based billing support for SaaS applications allowed-tools: Read, Glob, Grep, Task, mcp__perplexity__search, mcp__microsoft-learn__microsoft_docs_search, mcp__context7__query-docs
Usage Metering Skill
Guidance for implementing usage tracking and metering infrastructure in SaaS applications.
MANDATORY: Documentation-First Approach
Before implementing usage metering:
- Invoke
docs-managementskill for billing and metering patterns - Verify patterns via MCP servers (perplexity for current best practices, microsoft-learn for Azure patterns)
- Base all guidance on official documentation and current industry standards
When to Use
- Implementing consumption-based pricing
- Tracking API calls, storage, compute, or feature usage
- Building usage dashboards and alerts
- Integrating with billing systems for usage-based charges
Core Concepts
Usage Event Types
Usage Categories:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Category โ Examples โ Billing Unit โ
โโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโค
โ API Calls โ Requests, queries, ops โ Per 1K calls โ
โ Compute โ CPU seconds, GPU hours โ Per hour โ
โ Storage โ GB stored, objects โ Per GB/month โ
โ Data Transfer โ Egress, ingress bytes โ Per GB โ
โ Seats/Users โ Active users, MAU โ Per user โ
โ Features โ Reports generated, exports โ Per action โ
โ Resources โ Projects, environments โ Per resource โ
โโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโ
Metering Patterns
Pattern Selection:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Pattern โ Use When โ Trade-offs โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโค
โ Real-time โ Need instant visibility โ Higher cost โ
โ Near-real-time โ 5-15 min latency OK โ Balanced โ
โ Batch โ Daily/hourly aggregation โ Lower cost โ
โ Sampling โ High volume, estimates OK โ Approximate โ
โ Hybrid โ Mix of above โ Complex โ
โโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโ
Implementation Patterns
Usage Event Model
// Core usage event structure
public sealed record UsageEvent
{
public required Guid EventId { get; init; } = Guid.NewGuid();
public required Guid TenantId { get; init; }
public required string MetricName { get; init; } // e.g., "api.requests"
public required decimal Quantity { get; init; }
public required string Unit { get; init; } // e.g., "count", "bytes"
public required DateTimeOffset Timestamp { get; init; }
public required string Source { get; init; } // e.g., "api-gateway"
public string? UserId { get; init; }
public string? ResourceId { get; init; }
public Dictionary<string, string> Dimensions { get; init; } = [];
public string? IdempotencyKey { get; init; }
}
// Aggregated usage for billing periods
public sealed record UsageAggregate
{
public required Guid TenantId { get; init; }
public required string MetricName { get; init; }
public required DateOnly PeriodStart { get; init; }
public required DateOnly PeriodEnd { get; init; }
public required decimal TotalQuantity { get; init; }
public required string Unit { get; init; }
public required int EventCount { get; init; }
public DateTimeOffset LastUpdated { get; init; }
}
Metering Service Interface
public interface IUsageMeteringService
{
// Record single usage event
Task RecordUsageAsync(
Guid tenantId,
string metricName,
decimal quantity,
string unit,
Dictionary<string, string>? dimensions = null,
string? idempotencyKey = null,
CancellationToken ct = default);
// Record batch of events
Task RecordBatchAsync(
IReadOnlyList<UsageEvent> events,
CancellationToken ct = default);
// Get current period usage
Task<UsageAggregate> GetCurrentUsageAsync(
Guid tenantId,
string metricName,
CancellationToken ct = default);
// Get historical usage
Task<IReadOnlyList<UsageAggregate>> GetUsageHistoryAsync(
Guid tenantId,
string metricName,
DateOnly startDate,
DateOnly endDate,
CancellationToken ct = default);
}
High-Volume Ingestion Pattern
// Buffered writer for high-throughput scenarios
public sealed class BufferedUsageWriter : IAsyncDisposable
{
private readonly Channel<UsageEvent> _channel;
private readonly IUsageEventStore _store;
private readonly Task _processorTask;
public BufferedUsageWriter(
IUsageEventStore store,
int batchSize = 100,
TimeSpan? flushInterval = null)
{
_store = store;
_channel = Channel.CreateBounded<UsageEvent>(
new BoundedChannelOptions(10_000)
{
FullMode = BoundedChannelFullMode.Wait
});
flushInterval ??= TimeSpan.FromSeconds(5);
_processorTask = ProcessEventsAsync(batchSize, flushInterval.Value);
}
public ValueTask RecordAsync(UsageEvent evt, CancellationToken ct = default)
=> _channel.Writer.WriteAsync(evt, ct);
private async Task ProcessEventsAsync(int batchSize, TimeSpan flushInterval)
{
var batch = new List<UsageEvent>(batchSize);
var timer = new PeriodicTimer(flushInterval);
while (await _channel.Reader.WaitToReadAsync())
{
// Drain available events up to batch size
while (batch.Count < batchSize &&
_channel.Reader.TryRead(out var evt))
{
batch.Add(evt);
}
if (batch.Count >= batchSize || await ShouldFlushAsync(timer))
{
await _store.WriteBatchAsync(batch);
batch.Clear();
}
}
// Flush remaining on shutdown
if (batch.Count > 0)
await _store.WriteBatchAsync(batch);
}
}
Architecture Options
Event Streaming Architecture
High-Volume Metering:
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ API Gateway โโโโโโถโ Event Hub/ โโโโโโถโ Stream โ
โ (emit) โ โ Kafka โ โ Processor โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโฌโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ Time-Series โ โ Aggregates โ โ Alerts โ
โ Store โ โ (Redis/SQL) โ โ Engine โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
Simple Database Pattern
Low-Volume Metering:
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ Application โโโโโโถโ Usage Table โโโโโโถโ Background โ
โ (record) โ โ (append) โ โ Aggregator โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโฌโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโ
โ Aggregates โ
โ Table โ
โโโโโโโโโโโโโโโ
Quota Enforcement
Quota Check Pattern
public sealed class QuotaEnforcementService(
IUsageMeteringService metering,
IEntitlementService entitlements,
ILogger<QuotaEnforcementService> logger)
{
public async Task<QuotaCheckResult> CheckQuotaAsync(
Guid tenantId,
string metricName,
decimal requestedQuantity,
CancellationToken ct = default)
{
// Get current usage
var currentUsage = await metering.GetCurrentUsageAsync(
tenantId, metricName, ct);
// Get entitlement limit
var limit = await entitlements.GetLimitAsync(
tenantId, metricName, ct);
if (limit is null)
{
return QuotaCheckResult.Unlimited();
}
var projectedUsage = currentUsage.TotalQuantity + requestedQuantity;
if (projectedUsage > limit.HardLimit)
{
logger.LogWarning(
"Quota exceeded for tenant {TenantId}, metric {Metric}",
tenantId, metricName);
return QuotaCheckResult.Denied(
current: currentUsage.TotalQuantity,
limit: limit.HardLimit,
requested: requestedQuantity);
}
if (projectedUsage > limit.SoftLimit)
{
return QuotaCheckResult.Warning(
current: currentUsage.TotalQuantity,
softLimit: limit.SoftLimit,
hardLimit: limit.HardLimit);
}
return QuotaCheckResult.Allowed(
remaining: limit.HardLimit - projectedUsage);
}
}
Rate Limiting vs Quota
Comparison:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Aspect โ Rate Limiting โ Quota/Metering โ
โโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโค
โ Time Window โ Seconds/minutes โ Hours/days/months โ
โ Purpose โ Protect system โ Enforce billing โ
โ Enforcement โ Hard block โ Soft/hard limits โ
โ Response โ 429 + retry-after โ 402/403 + upgrade โ
โ Tracking โ In-memory/Redis โ Durable storage โ
โ Precision โ Approximate OK โ Exact required โ
โโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโ
Use BOTH:
- Rate limiting: System protection (per-second/minute)
- Quota: Business limits (per-month billing cycles)
References
Load for detailed implementation:
references/event-ingestion.md- High-throughput event capture patternsreferences/aggregation-strategies.md- Time-series aggregation and rollups
For billing integration patterns, see the billing-integration skill.
Related Skills
billing-integration- Payment processing and invoicingentitlements-management- Feature gating and limitssubscription-models- Pricing tier definitions
Last Updated: 2025-12-29
Repository

melodic-software
Author
melodic-software/claude-code-plugins/plugins/saas-patterns/skills/usage-metering
3
Stars
0
Forks
Updated1d ago
Added6d ago