Customer Domain¶
The customer_domain bounded context owns the customer entity lifecycle — from signup through churn. It is the anchor that all other domains reference via customer_id.
Entities¶
src.domain.customer.entities ¶
Customer entity – core of the Customer bounded context.
An Entity has a unique identity (customer_id) and mutable lifecycle state. Business rules about customers live here, not in the API or infrastructure layers.
Classes¶
Customer
dataclass
¶
Represents a B2B SaaS customer account.
The customer entity owns lifecycle state (active vs churned) and exposes domain methods that encapsulate churn-relevant business rules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
customer_id
|
str
|
Unique identifier (UUID string). |
required |
industry
|
Industry
|
Vertical segment, used for cohort analysis. |
required |
plan_tier
|
PlanTier
|
Commercial tier (starter / growth / enterprise). |
required |
signup_date
|
date
|
Date of first contract activation. |
required |
mrr
|
MRR
|
Monthly Recurring Revenue value object. |
required |
churn_date
|
date | None
|
Date of cancellation; None means still active (right-censored). |
None
|
Source code in src/domain/customer/entities.py
Attributes¶
property
¶Days from signup to churn (or today if still active).
Used as the time axis in survival analysis models.
property
¶True if customer is within the critical first-90-day onboarding window.
20–25% of voluntary churn occurs in this window (per Forrester data).
property
¶Human-readable annual revenue that would be lost if this customer churns.
Functions¶
Record the churn event.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
churn_date
|
date
|
The date cancellation was confirmed. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If churn_date precedes signup_date or customer already churned. |
Source code in src/domain/customer/entities.py
Value Objects¶
src.domain.customer.value_objects ¶
Value objects for the Customer domain.
Value objects are immutable and compared by value, not identity. They encapsulate business rules about what constitutes a valid value.
Classes¶
PlanTier ¶
Bases: StrEnum
The commercial tier a customer is on.
Tier correlates with feature access, support SLA, and churn risk profile. Enterprise customers have dedicated CSMs and lower base churn rates. CUSTOM represents bespoke enterprise contracts — the ceiling of the tier ladder. FREE represents the freemium tier (zero MRR); the highest-leverage conversion event in SaaS is free → paid when a customer hits a feature data-sharing limit.
Source code in src/domain/customer/value_objects.py
Industry ¶
Bases: StrEnum
Vertical industry segment.
Used for cohort segmentation and industry-specific churn benchmarking.
Source code in src/domain/customer/value_objects.py
MRR
dataclass
¶
Monthly Recurring Revenue in USD.
Enforces non-negative constraint. Used for business impact calculations (e.g. revenue at risk = MRR × churn_probability).
Source code in src/domain/customer/value_objects.py
Repository Interface¶
src.domain.customer.repository ¶
CustomerRepository – abstract port (interface) for the Customer domain.
Infrastructure implementations live in src/infrastructure/repositories/. The domain layer depends only on this interface, never on DuckDB directly.
Classes¶
CustomerRepository ¶
Bases: ABC
Port (interface) for persisting and retrieving Customer entities.
Source code in src/domain/customer/repository.py
Functions¶
abstractmethod
¶Retrieve a customer by their unique ID.
Returns:
| Type | Description |
|---|---|
Customer | None
|
Customer entity, or None if not found. |
abstractmethod
¶Return all customers who have not yet churned.
Used for batch churn scoring runs.
abstractmethod
¶Return a random sample of n customers (any churn status).
Business Context
Used by the demo list endpoint to seed load-test tooling and the UI customer picker. Deterministic seed (REPEATABLE 42) ensures the same customers are returned across requests for reproducibility.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of customers to sample (caller must clamp to safe max). |
required |