Concepts
HUME is multi-tenant: each tenant has its own API key and isolated catalog, subscriptions, usage, and billing data. There is no cross-tenant access.
Event-sourced state
All writes append to a single per-tenant event log. Current billing state is a read model rebuilt by applying events — the same ReadModel.Apply(event) path runs for live writes and
for replay. A broken event log is a startup error, not silent data loss.
Each user-facing operation appends one primary event; some also emit linked side effects (for example adjustment.posted or refund.issued after subscription.plan_changed,
or materialized lifecycle events like subscription.canceled). Synthetic monthly_tracked_users usage may be appended as well.
List the journal with GET /events (newest first), inspect projected state with GET /state, or subscribe via webhooks.
Storage and recovery
The event log is append-only. If a read-model snapshot is available and its version matches the current engine version, recovery loads the snapshot plus the event tail; an outdated snapshot is ignored and the full log is replayed. Snapshots are written periodically and on graceful shutdown.
monthly_tracked_users is maintained automatically: the first billing event for a user in a
calendar month creates a synthetic usage event with quantity = 1. The metric itself is
created by a regular metric.created event and survives replay.
Entity identifiers
Entity ids use {prefix}_{ulid} (for example usr_01ARZ3NDEKTSV4RRFFQ69G5FAV). Prefixes identify the type (usr, met, pln, sub, evt, ten, …); the
suffix is a monotonic ULID.
Core entities
Metrics and features exist in a tenant catalog; plans bind them with per-tariff pricing and entitlements. See Catalog vs plans for the full mental model (what is shared vs what is per plan).
| Entity | Role |
|---|---|
| User | Billable account; linked to subscriptions and usage |
| Metric | Measurable unit in the tenant catalog (e.g. api_requests) — identity only; pricing is on each plan |
| Plan | Monthly price + per-metric rules + groups/limits + attached features |
| Feature | Entitlement in the catalog (e.g. exports); each plan chooses which features to grant |
| Subscription | User on a plan with lifecycle state |
| Invoice | Generated JSON with line items for a billing window |
User timezone
Each user has an IANA timezone (default UTC, set at create or via POST /users/{id}/timezone). It drives:
- subscription billing period boundaries (
billing_timezonecopied at subscribe time) - calendar-month buckets for
monthly_tracked_users - plan
classifyroutes with time, calendar, quantity, period usage, and source predicates (UTC and user-local variants)
Updating timezone later does not rewrite active subscription periods.
Abstract billing units
All money-like fields are integers in abstract billing units. There is no currency field
in the API. Display labels (USD, EUR, credits, tokens), taxes, discounts, and FX are downstream
concerns — apply them when charging.