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).

EntityRole
UserBillable account; linked to subscriptions and usage
MetricMeasurable unit in the tenant catalog (e.g. api_requests) — identity only; pricing is on each plan
PlanMonthly price + per-metric rules + groups/limits + attached features
FeatureEntitlement in the catalog (e.g. exports); each plan chooses which features to grant
SubscriptionUser on a plan with lifecycle state
InvoiceGenerated 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_timezone copied at subscribe time)
  • calendar-month buckets for monthly_tracked_users
  • plan classify routes 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.