Skip to main content

Webhook Dispatcher — Domain Model

Status: populated Owner: Platform Engineering Last updated: 2026-04-18 Companion: SERVICE_OVERVIEW · DATA_MODEL · EVENT_SCHEMAS

1. Core Aggregates

WebhookConfig (root)

Represents a customer-registered webhook endpoint. Owns the signing secret and URL.

FieldTypeNotes
webhookIdWebhookId (UUIDv4)Primary key
accountIdAccountId (UUIDv4)Owner account; isolation boundary
urlWebhookUrl (VO)HTTPS URL; validated at registration
secretWebhookSecret (VO)HMAC-SHA256 signing key; stored encrypted
descriptionstring | nullHuman-readable label
eventsWebhookEventType[]Event filter (e.g. ['DLR_DELIVERED', 'DLR_FAILED'])
isActivebooleanSoft-disable without deletion
createdAtInstantRegistration timestamp
updatedAtInstantLast modification

DeliveryAttempt (root)

Represents one delivery attempt for a single webhook.dispatch event to a single WebhookConfig. Accumulates per-attempt results.

FieldTypeNotes
attemptIdAttemptId (UUIDv4)Primary key
deliveryIdDeliveryId (UUIDv4)Groups all attempts for the same event+webhook
webhookIdWebhookIdTarget webhook
accountIdAccountIdOwner account
eventIdstringSource webhook.dispatch.eventId (dedup key)
attemptNumber1..5Current attempt
statusDeliveryStatusSee §3
httpStatusCodenumber | nullResponse status code
responseBodyPreviewstring | nullFirst 512 chars of response
errorMessagestring | nullNetwork error or timeout message
scheduledAtInstantWhen this attempt was/is due
attemptedAtInstant | nullWhen HTTP request was made
nextRetryAtInstant | nullNull for final attempt or SUCCESS

2. Value Objects

VOInvariant
WebhookIdUUIDv4 branded
DeliveryIdUUIDv4 branded; stable across all retries of same event
WebhookUrlHTTPS only; valid URL; max 2048 chars
WebhookSecretNon-empty; 16–128 chars; stored AES-256-GCM encrypted
WebhookEventTypeEnum: DLR_DELIVERED, DLR_FAILED, DLR_UNDELIVERED, DLR_EXPIRED, DLR_REJECTED, DLR_UNKNOWN

3. DeliveryStatus Enum

StatusMeaning
PENDINGQueued for first attempt or retry
IN_FLIGHTHTTP request in progress
SUCCESS2xx response received
FAILED_RETRYNon-2xx or timeout; retry scheduled
DEAD_LETTERMax attempts exhausted; no further retries

4. Retry Schedule

AttemptDelay after previous failure
1Immediate (from event receipt)
230 seconds
35 minutes
430 minutes
52 hours
— (after attempt 5 fails)8 hours — dead-letter after this

Total retry window: ≈ 10.5 hours from first attempt.

5. Domain Events (internal)

EventTrigger
WebhookDelivered2xx response on any attempt
WebhookRetryScheduledNon-2xx or timeout; attempt < 5
WebhookDeadLetteredAttempt 5 fails
WebhookConfigCreatedNew webhook registered
WebhookConfigDeactivatedisActive set to false

6. Invariants

  1. deliveryId is stable: all retry attempts for the same (eventId, webhookId) pair share the same deliveryId.
  2. DeliveryStatus transitions are monotone: no transition from SUCCESS or DEAD_LETTER.
  3. WebhookUrl must use HTTPS scheme; plain HTTP rejected at registration.
  4. A WebhookConfig with isActive = false receives no dispatch attempts.
  5. Maximum 10 WebhookConfig records per accountId.