Sending policy

Never at 3am.
Never on Sunday.
Always at 10:00.

Set the quiet hours, the allowed days, and the daily cap. The dispatcher honours them in the lead local time zone.

Workspace sending policy

Lead time zone fallback
UTC (override per lead)
Quiet hours
09:00to18:00
Allowed days
SunMonTueWedThuFriSat
Daily message cap
120 per day

Customers do not unsubscribe because the message was wrong. They unsubscribe because the timing was rude.

The dispatcher

What happens when a step fires outside the window.

Auto-defer

Outside hours? Defer to the next eligible window.

If a step is due at 23:42 lead time, the dispatcher does not send. It pushes nextRunAt to the next morning, releases the claim, and moves on.

Outside the day mask? Defer until the next allowed day. Above the daily cap? Defer until tomorrow.

Dispatcher tick · 23:42 UTC

Lead in IST (UTC+5:30): 05:12 local

Window09:00 to 18:00 IST
DecisionOutside window. Defer.
Next attemptToday 09:00 IST (08:30 UTC)

Per-lead overrides

Set the time zone on the lead, the workspace falls back gracefully.

Lead.timezone

A lead with a known time zone overrides the workspace fallback.

Capture the lead time zone via the import CSV or the API. The dispatcher uses the lead time zone first, the workspace fallback second.

Bad time zone string? The system falls back to UTC and logs it. No silent skips.

Resolution order

1Lead.timezoneAmerica/Los_Angeles
2Workspace.sendingTimezoneUTC
3System fallbackUTC

Tech specs

Hour window
0..23 (start) and 1..24 (end), end exclusive
Day mask
Bit per day, bit0=Sun .. bit6=Sat (default 127 = all)
Daily cap
null = unlimited; integer cap per workspace per day
Time zone source
Lead.timezone (override) → Workspace.sendingTimezone → UTC
Defer behaviour
Outside window → next hour. Outside day mask → next allowed day.
Audit
Every policy change written to AuditLog with actor + IP

Send when the time is right. Or do not send at all.