Usage-based billing engine for Go

Bill your SaaS

Meter usage, check entitlements, manage subscriptions, generate invoices — high-performance, multi-tenant, and provider-agnostic.

$go get github.com/xraph/ledger
Meter()
Entitled
Track
Invoice
api.1k
metered
quota.ok
<1ms
inv.gen
$49.00
10K+ events/s
Multi-Tenant
<1ms Checks
Type-Safe
Features

Everything you need for SaaS billing

Ledger handles the hard parts — metering, entitlements, pricing, and invoicing — so you can focus on your product.

Sub-Millisecond Entitlements

Check feature access with <1ms latency using intelligent caching. Built for high-frequency permission checks.

entitlement.go
"text-fd-muted-foreground/60 italic">// Check entitlement (<1ms with cache)
result, _ := engine.Entitled(ctx, "api_calls")
 
if result.Allowed {
fmt.Printf("Remaining: %d/%d\n",
result.Remaining, result.Limit)
"text-fd-muted-foreground/60 italic">// Process request...
}

High-Throughput Metering

Ingest 10K+ usage events per second with batched processing. Non-blocking API calls with automatic flush.

metering.go
"text-fd-muted-foreground/60 italic">// Meter usage (non-blocking, batched)
engine.Meter(ctx, "api_calls", 100)
engine.Meter(ctx, "storage_gb", 5)
engine.Meter(ctx, "seats", 1)
 
"text-fd-muted-foreground/60 italic">// Auto-batches every 100 events or 5s
"text-fd-muted-foreground/60 italic">// 10K+ events/second throughput

Flexible Pricing Models

Graduated tiers, volume pricing, per-seat, flat-rate, and hybrid models. Define complex pricing with simple structs.

pricing.go
Pricing: &plan.Pricing{
BaseAmount: types.USD(4900), "text-fd-muted-foreground/60 italic">// $49
Tiers: []plan.PriceTier{
{UpTo: 1000, UnitAmount: types.Zero()},
{UpTo: 5000, UnitAmount: types.USD(10)},
{UpTo: -1, UnitAmount: types.USD(5)},
},
}

Subscription Lifecycle

Manage trials, upgrades, downgrades, and cancellations. Automatic proration and period management.

subscription.go
"text-fd-muted-foreground/60 italic">// Create subscription with trial
sub := &subscription.Subscription{
PlanID: planID,
Status: subscription.StatusTrialing,
TrialEnd: time.Now().AddDate(0, 0, 14),
}
 
"text-fd-muted-foreground/60 italic">// Upgrade/downgrade
engine.ChangePlan(ctx, subID, newPlanID)

Automatic Invoicing

Generate invoices with line items, taxes, and discounts. Integrates with payment providers for collection.

invoice.go
"text-fd-muted-foreground/60 italic">// Generate invoice for period
invoice, _ := engine.GenerateInvoice(
ctx, subscriptionID)
 
"text-fd-muted-foreground/60 italic">// Invoice includes:
"text-fd-muted-foreground/60 italic">// - Base subscription: $49.00
"text-fd-muted-foreground/60 italic">// - API overage (5k): $50.00
"text-fd-muted-foreground/60 italic">// - Discount(10%): -$9.90
"text-fd-muted-foreground/60 italic">// Total: $89.10

Type-Safe Money

Integer-only currency handling with zero floating-point errors. Multi-currency support with proper decimal handling.

money.go
"text-fd-muted-foreground/60 italic">// All amounts are integer cents
amount := types.USD(4999) "text-fd-muted-foreground/60 italic">// $49.99
tax := amount.Multiply(0.08) "text-fd-muted-foreground/60 italic">// 8% tax
total := amount.Add(tax)
 
"text-fd-muted-foreground/60 italic">// Multi-currency support
eur := types.EUR(3999) "text-fd-muted-foreground/60 italic">// €39.99
gbp := types.GBP(2999) "text-fd-muted-foreground/60 italic">// £29.99
 
"text-fd-muted-foreground/60 italic">// No floating-point errors ever
RAG Ingestion Pipeline

From document to searchable context.

Weave orchestrates the entire ingestion lifecycle — tenant scoping, text chunking, embedding generation, and vector storage.

Automatic Tenant Scoping

Every ingestion and retrieval is stamped with TenantID and AppID from context. Collection and chunk isolation is enforced at the store layer — no tenant can access another's data.

Configurable Chunk Strategies

Recursive or fixed-size chunking with configurable token size and overlap. Per-collection strategy overrides let you tune chunking for different document types.

Lifecycle Extension Hooks

OnIngestCompleted, OnRetrievalFailed, and 12 other lifecycle events. Wire in metrics, audit trails, or custom processing logic without modifying engine code.

Ingest()
doc.ingest
Chunkerrecursive
Embeddertext-emb-3
doc.loaded
✓ Parsed
chunks.created
⟳ Chunking
vec.stored
✓ Indexed
Ready
Processing
Chunking
Failed
Developer Experience

Simple API. Powerful billing.

Setup plans and track usage in under 20 lines. Ledger handles metering, entitlements, and invoicing.

Setup Billing
main.go
1package main
2 
3import (
4 "context"
5 "log/slog"
6 "time"
7 
8 "github.com/xraph/ledger"
9 "github.com/xraph/ledger/plan"
10 "github.com/xraph/ledger/store/postgres"
11 "github.com/xraph/ledger/types"
12)
13 
14func main() {
15 ctx := context.Background()
16 
17 "text-fd-muted-foreground/60 italic">// Initialize billing engine
18 engine := ledger.New(
19 postgres.New(pool),
20 ledger.WithMeterConfig(100, 5*time.Second),
21 ledger.WithEntitlementCacheTTL(30*time.Second),
22 )
23 
24 "text-fd-muted-foreground/60 italic">// Create a usage-based plan
25 p := &plan.Plan{
26 Name: "Pro Plan",
27 Slug: "pro",
28 Features: []plan.Feature{
29 {
30 Key: "api_calls",
31 Type: plan.FeatureMetered,
32 Limit: 10000,
33 },
34 },
35 Pricing: &plan.Pricing{
36 BaseAmount: types.USD(4900), "text-fd-muted-foreground/60 italic">// $49.00
37 },
38 }
39 
40 engine.CreatePlan(ctx, p)
41}
Track Usage
usage.go
1package main
2 
3import (
4 "context"
5 "fmt"
6 
7 "github.com/xraph/ledger"
8)
9 
10func trackUsage(
11 engine *ledger.Ledger,
12 ctx context.Context,
13) {
14 "text-fd-muted-foreground/60 italic">// Set tenant context
15 ctx = context.WithValue(ctx, "tenant_id", "tenant_123")
16 ctx = context.WithValue(ctx, "app_id", "app_456")
17 
18 "text-fd-muted-foreground/60 italic">// Check entitlement (<1ms with cache)
19 result, _ := engine.Entitled(ctx, "api_calls")
20 
21 if result.Allowed {
22 fmt.Printf("Quota: %d/%d remaining\n",
23 result.Remaining, result.Limit)
24 
25 "text-fd-muted-foreground/60 italic">// Meter usage (non-blocking, batched)
26 engine.Meter(ctx, "api_calls", 1)
27 
28 "text-fd-muted-foreground/60 italic">// Process API call...
29 } else {
30 fmt.Printf("Quota exceeded: %s\n", result.Reason)
31 "text-fd-muted-foreground/60 italic">// Return 429 Too Many Requests
32 }
33}

Start building with Ledger

Add production-grade usage billing to your Go service in minutes. Ledger handles metering, entitlements, subscriptions, and invoicing out of the box.

$go get github.com/xraph/ledger