Skip to main content

Domain Model

The domain model consists of entities, value objects, and aggregates that represent the billing domain.

Canonical reference

This page is an English summary. The canonical, in-depth specification is docs/internals/domain-model.md (see the Documentation Map). When details differ, the internals spec and the code win.

Entity Relationship Diagram

Legend
  • Account is an external boundary (managed outside this domain)
  • Contract is the event-sourced aggregate root (ContractAggregate)
  • Money is a big.Rat-based value object; IDs are ULID-generated
  • TrialConfiguration / SuspensionConfiguration are value objects (no persistence ID)

Contract Aggregate

The contract is the central entity, modeled as an event-sourced aggregate root. It manages the full lifecycle of a billing agreement.

States

StatusDescription
draftContract created but not yet active
trialingIn trial period
activeCurrently active and billable
past_duePayment overdue (dunning in progress)
suspendedTemporarily suspended
cancelledPermanently cancelled
expiredTerm ended without renewal

Contract Types

TypeDescription
one_timeSingle purchase, no recurring billing. May omit the billing interval entirely (#218) — see the internals spec for details
subscriptionRecurring billing at a fixed interval
usage_basedCharges based on metered usage

Operations

The aggregate supports lifecycle management, price changes, trials, and scheduled cancellations. All operations emit domain events for the event store.

For complete struct definitions, commands, and getters, see Domain Types Reference.

Invoice

Invoices are generated by BillingService and track the billing calculation result.

States

Invoices support a revision chain (void-and-recreate) for corrections: originalInvoiceID points to the chain root, revisionOf points to the direct parent.

For construction options, methods, and line item details, see Domain Types Reference.

Payment

Tracks individual payment transactions with idempotency keys for duplicate prevention.

States: pendingcompleted / failedpartially_refunded / refunded / charged_back

For complete type definitions, see Domain Types Reference.

Product and Price

Following the Stripe pattern of separating what you sell from how you charge:

  • Product — Defines the offering: name, features, usage metrics
  • Price — Defines billing: amount, currency, cycle, pricing model. Immutable after creation — to change pricing, create a new Price

Pricing models: FlatPrice, TieredPrice (graduated or volume), UsagePrice

For complete type definitions and pricing model details, see Domain Types Reference.

Credit Ledger

FIFO-based credit system for handling prorations, cancellation credits, and adjustments. Credits are automatically consumed during invoice generation, oldest first.

Reasons: proration, cancellation, manual_adjustment, refund_conversion, goodwill

For complete type definitions, see Domain Types Reference.

Shared Value Objects

TypeDescription
MoneyArbitrary-precision (big.Rat) monetary value with currency. Currencies: JPY, USD, EUR
DateRangeHalf-open interval [start, end) for billing periods
ID TypesULID-based: ContractID, InvoiceID, PaymentID, ProductID, PriceID, etc.
ClockTime abstraction (SystemClock for production, FixedClock for tests)
DomainErrorStructured errors with ErrorCode for business vs technical errors

For complete value object APIs, see Domain Types Reference.