routing-engine — Domain Model
Status: populated | Last updated: 2026-04-18
1. Aggregates & Entities
1.1 RoutingRule (Aggregate Root)
Represents a rule that maps a destination prefix + account context to an ordered set of operator candidates and a routing strategy.
| Attribute | Type | Description |
|---|---|---|
id | uuid | Primary key |
accountId | uuid | null | Scoped to account or global (null) |
prefixId | uuid | FK → destination_prefixes |
strategy | RoutingStrategy | COST / PRIORITY / FAILOVER |
isActive | boolean | Soft-enable/disable without deletion |
priority | integer | Rule evaluation order when multiple rules match |
createdAt | timestamp | Immutable audit field |
updatedAt | timestamp | Audit field |
1.2 RoutingRuleOperator (Entity within RoutingRule)
Junction entity linking a rule to one or more operators with per-operator cost and priority metadata.
| Attribute | Type | Description |
|---|---|---|
ruleId | uuid | FK → routing_rules |
operatorId | uuid | FK → operators |
cost | numeric(10,6) | Cost per message (used by COST strategy) |
priority | integer | Priority rank (1 = highest, used by PRIORITY + FAILOVER) |
1.3 DestinationPrefix (Entity)
A phone number prefix (E.164) used to match the to field in a routing request.
| Attribute | Type | Description |
|---|---|---|
id | uuid | Primary key |
prefix | varchar(20) | E.164 prefix, e.g. +1, +447, +9375 |
country | char(2) | ISO 3166-1 alpha-2 country code |
description | text | Human-readable label |
1.4 Operator (Entity — read from ops_routing.operators)
A projection of operator data needed by the routing engine. Full operator management is owned by operator-management-service.
| Attribute | Type | Description |
|---|---|---|
id | uuid | Primary key (shared with operator-management-service) |
name | varchar(100) | Display name |
host | varchar(255) | SMPP host |
port | integer | SMPP port |
systemId | varchar(64) | SMPP bind credential |
tpsLimit | integer | Max transactions per second |
messageTypes | text[] | Supported message types (SMS, FLASH, etc.) |
2. Value Objects
| Value Object | Fields | Description |
|---|---|---|
RoutingDecision | operatorId, host, port, systemId, tpsLimit, strategy, resolvedAt | Immutable result of a routing evaluation; cached in Redis |
OperatorHealthState | operatorId, status: HealthStatus, updatedAt | Current health snapshot; written to Redis from NATS events |
PrefixMatch | prefix, matchLength | Result of longest-prefix matching against to number |
3. Enumerations
enum RoutingStrategy {
COST = 'COST', // select operator with lowest cost
PRIORITY = 'PRIORITY', // select operator with lowest priority number
FAILOVER = 'FAILOVER', // try operators in priority order; pick first healthy
}
enum HealthStatus {
BOUND = 'BOUND', // operator SMPP session is active
UNBOUND = 'UNBOUND', // operator SMPP session is down
FAILBACK = 'FAILBACK', // operator recovering from outage
}
enum MessageType {
SMS = 'SMS',
FLASH = 'FLASH',
WAP = 'WAP',
}
4. Routing Strategy State Machine
┌──────────────────────────────────────────────────────┐
│ SelectOperator called │
└──────────────────┬───────────────────────────────────┘
▼
┌───────────────────────┐
│ Check Redis cache │
└────┬──────────────────┘
HIT ◄─────┘ └────► MISS
│ │
▼ ▼
Return Longest-prefix match
cached (destination_prefixes)
decision │
┌─────▼──────┐
│ Load rules │ (routing_rules + operators)
└─────┬──────┘
│
┌────────────▼────────────┐
│ Filter: healthy only │ (operator:health Redis)
└────────────┬────────────┘
│
┌──────────────┼──────────────┐
COST PRIORITY FAILOVER
│ │ │
min(cost) min(priority) first healthy
│ │ in priority order
└──────────────┴──────────────┘
│
┌──────▼───────┐
│ Write cache │ TTL 300s
└──────┬───────┘
▼
Return OperatorConfig