SabFlow · Scheduling

Send at the right time, in the right timezone

Scheduler is the temporal layer underneath every flow, broadcast and reminder in SabNode. Express schedules in plain English, cron syntax, or relative time. Respect each contact's local timezone. Skip holidays and blackout windows. Recover gracefully from outages with bounded backfill.

  • Per-contact local timezone delivery
  • Cron, one-off and relative recurring
  • Holiday calendars and blackout windows
  • Backfill control after outages
The problem

Sending at 4:30am is a brand-damaging accident

Every operator has a story. A scheduled "good morning" template that fired at 4:30am because the cron ran in UTC. A Black Friday campaign that hit Australia first, then EU, then US — meaning the inbox was already full of competitors by the time the US woke up. A polling reminder that landed at 11pm on Election Day. A condolence message that auto-sent on a public holiday because nobody updated the calendar.

These accidents have the same root cause: time is hard, and most platforms treat it casually. They store cron expressions, hope the server clock is right, and assume the user knows what timezone they configured. Recipient timezone is an afterthought. Holidays do not exist. Blackout windows are a feature request from 2019 that nobody shipped.

Scheduler in SabNode treats time as a first-class problem. Every schedule has an explicit timezone — server, business, or recipient. Holiday calendars are pluggable per region. Blackout windows enforce hard "do not send" rules even if a flow tries. Outage backfill is bounded so a 6-hour scheduler downtime does not unleash a 6-hour avalanche of belated messages on customers. The defaults are paranoid because the stakes are.

What it is

Scheduler, in depth.

Scheduler powers four user-visible concepts: cron triggers (fire a flow on a schedule), broadcast scheduling (send a campaign at a specific time), Wait nodes (pause a flow until a condition), and reminders (one-off contact-specific events). Underneath, they share a single durable scheduling engine with millisecond precision, exactly-once semantics, and dynamic timezone resolution. Whether you set up a recurring "every Tuesday at 9am IST" or a one-off "send when the customer's appointment is 24 hours away", the same primitives apply.

Timezone handling is per-schedule and per-contact. A broadcast can target "9am in the recipient's local timezone", in which case Scheduler resolves each contact's timezone (from CRM field, IP geolocation fallback, or business default) and stages the send for the right wall-clock moment. A flow Wait can pause "until next Monday 10am IST" globally or "until tomorrow 9am in contact timezone" per contact. The engine indexes upcoming sends by minute-bucket per timezone so peak-hour batches do not stall.

Holiday calendars are a managed resource. We ship calendars for India (national + major state holidays), US, UK, EU countries, UAE, Singapore, Australia and 40 more. You can layer custom dates (your company off-days, marketing blackouts, religious observances per audience). When a schedule lands on a calendar date with "skip" rule, it shifts to the next valid moment. When it lands with "send" rule, it fires anyway. Per-channel rules — a billing reminder still goes out on a public holiday, but a marketing nudge does not.

Blackout windows are hard constraints. You declare "never send marketing between 9pm and 9am in recipient timezone" at the tenant level, and Scheduler enforces it across every flow, broadcast and reminder. A flow that hits a blackout pauses until the window opens. A broadcast scheduled inside a blackout shifts to the edge. This is the safety net against the 4:30am accident. For transactional messages (order shipped, OTP), you can declare exceptions explicitly — but the default is conservative.

Capabilities

Everything you get with Scheduler.

7 capabilities
01

Per-contact timezone resolution

Pick from CRM timezone field, IP geolocation, country code from phone number, or tenant default — in priority order. Missing data falls back to your business timezone. Every scheduled send carries the resolved timezone in its trace.

02

Cron and human syntax

Full cron-with-seconds (`0 0 9 * * MON-FRI`) for power users, plus human syntax for everyone else ("every Monday at 9am", "first day of each month at noon"). Both compile to the same internal representation and validate at save time.

03

Holiday calendars built in

Curated calendars for 50+ countries, updated annually. Custom calendars per tenant for your company holidays. Skip-or-send rule per schedule. Surface upcoming holidays in the schedule preview so you see what the next 30 days look like.

04

Blackout windows

Tenant-wide hard rules — never send marketing between 9pm-9am in contact timezone, never send anywhere on Republic Day. Exceptions declared explicitly per message category. Enforcement is at send-time, not configure-time — even ad-hoc flows respect it.

05

Outage backfill control

After a Scheduler outage or maintenance window, missed sends queue with a configurable backfill policy: send all (max 30 min late), send latest only, or skip entirely. Prevents a 6-hour outage from creating a 6-hour avalanche of stale messages.

06

Send-time optimisation

Optional ML-driven mode: for each contact, predict the hour-of-day with highest historical engagement and stage the send there. Falls back to the configured time if the contact has too little history. Lifts engagement 8-15% on broadcast campaigns.

07

Exactly-once delivery

Schedule entries have idempotency keys and are stored durably. A worker crash or deploy mid-send does not double-fire. Recovery resumes from the last committed state. We have run 4 billion+ scheduled events with no observed duplicate sends.

Use cases

Built for the way teams actually work.

E-commerce
Case 01

Black Friday timezone rollout

Single broadcast scheduled at 9am recipient-local. Scheduler stages 240,000 contacts across 14 timezones. AU fires first at midnight UTC, EU at 7am UTC, US at 13:00 UTC. No support team scrambling, no time-blocked microsegments. Engagement uplift of 23% vs flat-time send.

SaaS
Case 02

Renewal reminder cadence

Each subscription emits three reminders: 30, 7, and 1 day before renewal. All in customer local time at 10am. Holiday calendar shifts the 1-day reminder if it lands on a Sunday. Blackout window blocks any send between 9pm-9am. Renewal CTR up 11% with cleaner timing alone.

Financial Services
Case 03

Monthly NBFC EMI nudge

Cron schedule on the 28th of each month at 11am IST. Skips public holidays in India (custom calendar with regional state holidays). Fires a flow that segments by overdue status and sends the appropriate template. Replaces a manual ops process that occasionally missed cycles.

Healthcare
Case 04

Appointment reminders in clinic chain

One-off schedule per booking — fires 24 hours before appointment in patient local time. Skips reminders for patients who replied "confirmed" in the last 6 hours. Blackout 9pm-9am for non-urgent reminders. No-show rate down from 18% to 11%.

SaaS
Case 05

Daily standup digest

Cron weekday at 9:15am IST. HTTP Request pulls yesterday's PRs, AI summarises, Slack post. Skips Indian holidays. Skips between 22 Dec and 2 Jan automatically via a "team off" custom calendar. Internal team relies on it as the daily anchor.

How it works

From signup to first send in minutes.

Scheduler is included on every SabNode workspace. No separate billing, no extra setup — flip it on from your workspace settings.

  1. 01

    Pick the schedule type

    One-off, recurring cron, recurring relative, or trigger-based wait. The editor previews the next 10 fire times so you can sanity-check before saving.

  2. 02

    Configure timezone behavior

    Send in business timezone, server timezone, or each recipient's local time. For local, pick the resolution priority chain (CRM, IP, country, default).

  3. 03

    Layer calendars and blackouts

    Attach a holiday calendar with skip-or-send rule. Inherit tenant blackout windows or override with an exception for transactional categories.

  4. 04

    Set backfill and retries

    Define behavior if Scheduler was down when this should have fired: backfill within N minutes, send latest only, or skip. Set retry count for failed dispatches.

  5. 05

    Monitor in the schedule view

    See upcoming fires, recently-fired with status, and skipped (with reason). Drill into any entry for the resolved timezone and the trace.

Plays well with

Works with the tools you already ship on.

Google CalendarOutlookSlackShopifyMeta WhatsApp Cloud APITwilioGmailRazorpay
Frequently asked

Questions about Scheduler.

Can't find what you're looking for? Talk to our team.

How is the recipient's timezone determined?
In priority order: (1) the contact's `timezone` CRM field if set, (2) IP-geolocation from the last web interaction within 30 days, (3) country code derived from phone number with a default city per country, (4) tenant business timezone as fallback. Each resolution is logged so you can audit why a contact got the time they did. For high-stakes campaigns, we recommend backfilling the CRM field via the bulk-update tool first.
Can blackout windows have exceptions for OTP and transactional?
Yes. Blackout windows are scoped by message category. The default policy is conservative — marketing and broadcasts respect the window, transactional categories (OTP, order updates, shipping, appointment) are exempt by default. You can customise the matrix per tenant. The send pipeline tags every outbound with its category so the rules apply automatically without flow authors thinking about it.
What is the smallest schedule resolution?
One-second resolution for cron and relative schedules. Per-contact timezone-aware sends round to the nearest minute (because resolving timezone-per-contact at sub-minute resolution is operationally expensive and rarely matters). For Wait nodes, durations down to 100ms are honored — useful for tight retries or rate-limited fan-out.
How does Scheduler handle daylight saving transitions?
All schedules use IANA timezone identifiers (e.g. `America/New_York`, not `EST`). When DST shifts, the wall-clock interpretation shifts with it — a "9am every Monday in America/New_York" cron fires at 9am EST in winter and 9am EDT in summer, automatically. The spring-forward gap (no 2:30am exists that day) shifts forward; the fall-back duplicate (two 1:30am moments) fires once on the first occurrence. Both edge cases are tested in our regression suite.
Can I see all upcoming scheduled events for a contact?
Yes. The contact detail page in CRM has a "Scheduled" tab showing every pending send for that contact across flows, broadcasts and reminders. You can cancel an individual entry, postpone it, or trigger it now. This is the right place to look when a customer calls asking "why did you message me yesterday but not today" — the audit log next to the upcoming queue tells the whole story.
What happens if a flow Wait node's deadline has already passed when the flow resumes?
Configurable per Wait node. Default behavior is to fire immediately on resume (the "expected window" is the relevant signal, not the precise timestamp). You can switch to "skip and continue" — the Wait counts as elapsed and the downstream node runs without the side effect. Or "abort flow" if the missed deadline invalidates the journey entirely (rare). Trace shows which path was taken and why.
How do I prevent a misconfigured cron from blasting customers?
Three safeguards. (1) Save-time validation rejects expressions that would fire more than once per minute against a non-trivial audience. (2) Pre-publish preview shows next 10 fire times and estimated audience volume — high volumes require a second person to approve. (3) Tenant rate limits cap total sends per hour, so even a misconfigured "every second" cron cannot trigger more than your plan allows. The combination makes 4:30am accidents very hard to ship.
SabFlow · Scheduling

Ship scheduler into production this week.

No credit card. No sales call required. Spin up a workspace, plug in a number, and your team is live in under an hour.