DLR Processor — Domain Model
Status: populated
Owner: Platform Engineering
Last updated: 2026-04-18
Companion: SERVICE_OVERVIEW · DATA_MODEL · EVENT_SCHEMAS
1. Core Aggregates
DeliveryReceipt (root)
Represents a single delivery receipt received from an operator, correlated to an outbound SMS.
| Field | Type | Notes |
|---|
receiptId | ReceiptId (UUIDv4) | Internal primary key; generated on first write |
messageId | MessageId (UUIDv4) | FK → orch.sms_messages; null until correlated |
accountId | AccountId (UUIDv4) | Resolved from message correlation |
operatorMessageId | string | Carrier-assigned ID; dedup key |
operatorId | OperatorId | Source operator |
rawStat | string | Original carrier stat or status string |
dlrStatus | DlrStatus | Canonical normalised status |
deliveredAt | Instant | Timestamp from carrier or receipt arrival |
errorCode | string | null | Carrier error code when FAILED/UNDELIVERED |
correlatedAt | Instant | When correlation succeeded |
createdAt | Instant | Insert timestamp |
OrphanedReceipt (root)
Holds DLRs that arrived with an operatorMessageId that cannot be correlated to any known sms_messages row.
| Field | Type | Notes |
|---|
orphanId | UUIDv4 | Primary key |
operatorMessageId | string | Original carrier ID |
operatorId | OperatorId | Source operator |
rawStat | string | Original carrier stat |
rawPayload | JSONB | Full inbound event payload |
receivedAt | Instant | Event arrival time |
resolvedAt | Instant | null | Set if later reconciled |
resolvedReceiptId | ReceiptId | null | Set when reconciled |
2. Value Objects
| VO | Invariant |
|---|
ReceiptId | UUIDv4 branded type |
MessageId | UUIDv4 branded type; validated against regex |
AccountId | UUIDv4 branded type |
OperatorId | UUIDv4 branded type |
DlrStatus | Enum; see §3 |
OperatorMessageId | Non-empty string; max 64 chars |
3. DlrStatus Canonical Enum
DlrStatus | Meaning | Billable |
|---|
DELIVERED | Handset confirmed delivery | Yes |
FAILED | Permanent delivery failure | Yes |
UNDELIVERED | Could not deliver; no retry possible | Yes |
EXPIRED | Message TTL elapsed before delivery | Yes |
REJECTED | Operator rejected before attempt | Yes |
UNKNOWN | Status cannot be determined | No |
4. SMPP stat Normalisation Map
SMPP stat value | → DlrStatus |
|---|
DELIVRD | DELIVERED |
UNDELIV | UNDELIVERED |
EXPIRED | EXPIRED |
DELETED | FAILED |
ACCEPTD | UNKNOWN |
REJECTD | REJECTED |
UNKNOWN | UNKNOWN |
FAILED | FAILED |
| (any other) | UNKNOWN |
5. Domain Events (internal)
| Event | Trigger | Key Fields |
|---|
DlrCorrelated | Receipt matched to message | messageId, accountId, dlrStatus |
DlrOrphaned | No match found | operatorMessageId, operatorId, rawStat |
DlrDuplicate | operatorMessageId already exists | operatorMessageId, existingReceiptId |
6. Invariants
operatorMessageId is globally unique within dlr.delivery_receipts (unique index enforces idempotency).
- Status transitions on
orch.sms_messages only occur for terminal DlrStatus values (DELIVERED, FAILED, UNDELIVERED, EXPIRED, REJECTED).
DlrStatus.UNKNOWN does not trigger billing events but does trigger webhook dispatch.
- An orphan record is written before any further processing; the NATS message is ACKed only after both DB writes succeed.