System Architecture Overview
The billing platform is a Rust workspace composed of 18 crates arranged in a layered dependency graph.
Crate Dependency Graph
┌─────────────┐
│ common │ Money, IDs, BillingError, types, tax trait
└──────┬──────┘
┌──────────────┼──────────────┬──────────────┐
▼ ▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│metering │ │ pricing │ │customers │ │ ledger │
└────┬────┘ └────┬─────┘ └──────────┘ └──────────┘
│ │
▼ ▼
┌─────────┐ ┌──────────┐
│ rating │◄──│ pricing │
└────┬────┘ └──────────┘
│
▼
┌──────────────┐
│ invoicing │ + ledger, wallet
└──────┬───────┘
│
┌─────────┼──────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌──────────┐
│dunning │ │payments│ │contracts │
└────────┘ └────────┘ └──────────┘
│
┌─────────┼──────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌───────────────┐
│ audit │ │ wallet │ │spend-alerts │
└────────┘ └────────┘ └───────────────┘
│
▼
┌───────────────────┐
│ api-gateway │ Axum HTTP server
└───────────────────┘
Technology Stack
| Component | Technology | Notes |
|---|---|---|
| Language | Rust 2021 | Fearless concurrency, zero-cost abstractions |
| HTTP Framework | Axum 0.7 | Tower middleware, typed extractors |
| Ledger | TigerBeetle | In-memory shim in dev; TB client in prod |
| Database | CockroachDB | REGIONAL BY ROW multi-region schema |
| Analytics | ClickHouse | Metering aggregation, MV queries |
| Event streaming | Kafka | billing.<service>.<event> topic naming |
| Cache | Redis | Rate limiting (token bucket), hot-path accumulators |
| Payments | Stripe | PaymentIntent API + webhook verification |
| Auth | JWT HS256 + API keys | Constant-time comparison |
| Serialization | serde + serde_json | All monetary i128 as string |
Deploy Architecture
Internet
│
▼
Caddy (TLS termination, reverse proxy)
│
├─► api.bill.sh → api-gateway (port 3000)
├─► docs.bill.sh → mdBook static site
└─► ui.bill.sh → Askama/HTMX server-rendered UI
Infrastructure: Hetzner VPS (Ubuntu 24.04, Docker 29.x)
Key Design Principles
- Correctness over performance: i128 pico-units eliminate money rounding bugs
- Pure functions for business logic:
rate_all(),prorate_days(),compute_true_up()have no I/O — deterministic and easily tested - Idempotency everywhere: All mutating operations safe to retry
- In-memory for development: All repositories have
InMemory*implementations — no database required for local dev or tests - Swap-in production backends: Implement
Repositorytraits with CockroachDB/ClickHouse/TigerBeetle for production
Service Crates
| Crate | Responsibility |
|---|---|
common | Shared types: Money, NanoMoney, typed IDs, Currency, BillingError, TaxAdapter |
metering | UsageEvent ingestion, MeterDefinition, aggregation, EventStore |
rating | PriceSheet, rate_all() pure engine, RatedLineItem |
pricing | CatalogService, PriceVersionService, plan/product/SKU CRUD |
subscriptions | SubscriptionService, state machine, proration engine |
invoicing | InvoicingService, CalculateFeesService, FinalizeService, CreditNoteService |
contracts | ContractService, amendment chain, coterm, commit draw-down |
ledger | TigerBeetle client wrapper, double-entry transfers |
dunning | DunningSchedule, retry scheduler |
payments | StripeClient, PaymentIntent, webhook verification |
notifications | Outbox pattern, webhook delivery, circuit breaker |
audit | AuditLog, 25+ action types, before/after state |
reporting | AR aging, MRR movements, deferred revenue (ASC 606) |
wallet | CreditWalletService, auto-recharge |
spend-alerts | SpendAlertService, SoftLimit/HardLimit |
customers | CustomerService, hierarchy, entity tree |
engine | BillingEngine orchestrator (ties all services together) |
demo | Seed data for development |