Communication — Common cases
"A new notification creates a job but does not send"
This is usually caused by Notification Settings at the Scheduler step. Check in order:
- Has the notification type been seeded into
NotificationOptionfor the BU? (A new type must be seeded before it can be sent.) - Does the BU have a subscriber/recipient? If not, the handler skips gracefully.
- Does Generator have a handler for the new type? A new feature may not have wired the route yet.
Real-world example: A new notification type is enabled for a BU, jobs are created, but customers receive nothing. → Narrow the bottleneck to Scheduler/Generator. → The new type has not been seeded into
NotificationOptionfor the BU → seed it before sending works.
Add a placeholder to a template
Templates use {{...}}. For example, booking-notification-checkout-instruction adds a checkout-instruction placeholder. Process:
- Add the placeholder to the template.
- Ensure the Generator handler provides a value for that placeholder when rendering.
- Missing placeholder data → renders empty (check fallback).
Real example:
{{INCIDENT_DETAILS_LINK}}points to/attendance/incident-management(there is no deep-link to a specific incident yet — switch to a deep-link when the route exists).
Turn off/reduce a notification type
Some situations need notification suppress:
| Case | How |
|---|---|
| Do not send notification for pending booking | Mute in the pending condition |
| Turn off booking notification by subscription config | Subscription setting |
Mute/suppress is notification-only: it does not change booking/enrollment/invoice state (see the "alert mute is notification-only" principle in Subscription).
Configure default recipients for a site
- Seed default recipient email for the site.
- Optionally copy email to the site contact.
"Customer receives duplicate email" (send side)
Different from duplicates in Platform (duplicate job creation), this is duplication during send. Prevent it with a send claim:
Created/RetryReady -> Sending (conditional update)If duplication still happens, check (1) whether OutgoingMessage is truly "one row/recipient/channel" (RecipientKeyHash stable?), (2) whether send claim is actually conditional on Status, and (3) whether AttemptNo is accidentally included.
Real-world example: One parent receives two identical booking-confirmation emails. → Send only once per person/channel. → Send claim moves
Created → Sendingconditionally on Status → the second worker cannot claim it again.
Campaign to many recipients: large payload
Use MessagingJob + Blob. Notes:
- Large content stays in Blob (
messaging-jobcontainer); SQL only keeps orchestration + blob name. - Retry reuses compatible blob payload; mismatched payload → stop + report conflict (do not overwrite).
Safe report-subscription cutover
Report subscription is a thin path with:
- Shadow mode + allowlist + one-owner guard so old and new schedulers never send the same report period together.
- Step-by-step cutover with rollback. Details: Report Subscription.
"Job was skipped/deactivated — why did it not send?"
When automation is skipped/deactivated, there is no delivery. The reason is in AutomationScheduler.DispatchResultJson (SkippedReasonCode/ConflictReasonCode/Summary) and support screens — not in the send pipeline.
Real-world example: Support is asked why a schedule reminder did not send. → Look in the right place instead of digging through the send pipeline. →
DispatchResultJsonshowsSkippedReasonCode→ automation was intentionally skipped, not send-failed.