Skip to Content
Reverse ETLScheduling

Scheduling

Scheduling determines when and how often a reverse ETL sync runs. Zeotap supports interval-based schedules for regular cadences, calendar-anchored schedules for month-end and nth-weekday recurrences, cron expressions for precise timing, and manual-only mode for on-demand execution.

Schedule Types

Interval-Based

The simplest scheduling option. Choose a fixed interval, and Zeotap runs the sync at that frequency.

IntervalUse Case
Every 15 minutesReal-time-ish activation (ad audiences, live dashboards)
Every 30 minutesNear-real-time CRM updates
Every hourStandard operational syncs
Every 6 hoursRegular enrichment updates
Every 12 hoursTwice-daily reporting syncs
Every 24 hoursDaily batch syncs

How it works: After each reverse ETL sync run completes, Zeotap schedules the next run at the current time plus the interval. If a run takes longer than the interval, the next run starts immediately after the previous one finishes (runs never overlap).

Cron-Based

For precise timing control, use a cron expression. Cron scheduling lets you specify exact times, days of the week, and days of the month.

Cron Syntax

Cron expression syntax breakdown

Common Cron Expressions

ExpressionDescription
0 * * * *Every hour, on the hour
*/15 * * * *Every 15 minutes
0 9 * * *Daily at 9:00 AM
0 9 * * 1-5Weekdays at 9:00 AM
0 0 * * *Daily at midnight
0 9,17 * * *Twice daily at 9 AM and 5 PM
0 0 1 * *First day of every month at midnight
0 6 * * 1Every Monday at 6:00 AM
30 8 * * 1-5Weekdays at 8:30 AM
0 */4 * * *Every 4 hours
0 9 L * *Last day of every month at 9:00 AM
0 9 * * 5LLast Friday of every month at 9:00 AM
0 9 * * 1#1First Monday of every month at 9:00 AM
0 9 L */3 *Last day of every third month — January, April, July, October
0 9 L 3,6,9,12 *Last day of every calendar quarter

Cron Special Characters

CharacterMeaningExample
*Every value* * * * * = every minute
,List of values0 9,17 * * * = 9 AM and 5 PM
-Range of values0 9 * * 1-5 = Mon through Fri
/Step values*/15 * * * * = every 15 min
LLast day of the month (day-of-month field)0 9 L * * = the 28th, 29th, 30th or 31st, whichever ends the month
L-NN days before the last day (day-of-month field)0 9 L-1 * * = the second-to-last day
LLast occurrence of a weekday (day-of-week field)0 9 * * 5L = the last Friday
#Nth occurrence of a weekday (day-of-week field)0 9 * * 3#2 = the second Wednesday

Named values (MON, JAN) and the Quartz ? and W characters are not supported — use numeric fields.

The two day fields are combined with AND, not OR. Standard cron ORs day-of-month and day-of-week when both are restricted; Zeotap ANDs them, and has always done so. 0 9 L * 5 therefore means “the last day of the month, if it is a Friday” — roughly twice a year — not “the last day, or any Friday”. 0 9 L * 1#1 asks for a day that is both the last of the month and the first Monday, which never exists, so it parses, saves, describes itself plausibly and never runs.

Restrict one day field and leave the other * unless you specifically mean the intersection. There is no “last business day of the month” expression — 0 9 L * 1-5 silently skips every month that ends on a weekend.

Zeotap refuses to save an expression that can never run at all (0 9 L * 1#1, 0 0 30 2 *), so the outright-impossible cases fail at save time rather than at tick time. An expression that runs rarely0 9 L * 5, the last day of a month when it happens to be a Friday — is accepted, because that may well be what you meant.

Calendar-Anchored

Some recurrences cannot be written as a fixed interval at all, because the gap between them changes: “the last day of every month” is 28, 29, 30 or 31 days later depending on where you are in the year, and “the first Monday of the month” moves with what weekday the month begins on.

These are what the L and # characters above express, and the schedule picker builds them for you: choose Recurring, set the unit to Months, and pick how the day is anchored.

AnchorRuns onCron it produces
Last day of the monthThe final day, every month0 9 L * *
A day of the weekThe first / second / … / last chosen weekday0 9 * * 1#1
A day of the monthA fixed day number0 9 15 * *

Setting Repeat every above 1 skips months. The step counts from January and restarts each year, so “every 3 months” on the last-day anchor gives you the last day of January, April, July and October — a month after each calendar quarter ends. Only the divisors of 12 (1, 2, 3, 4, 6, 12) produce an even cadence; “every 5 months” fires in January, June and November and then jumps back two months. For true calendar quarters, use a month list in the custom-cron editor: 0 9 L 3,6,9,12 *. The picker warns you when the step you have chosen is uneven.

A day the month does not have is skipped, not moved. A schedule on day 31 does not run in February, April, June, September or November, and the fifth Tuesday of the month exists only in some months. Neither is shifted to the nearest valid day — the run simply does not happen. Use Last day of the month (or the Last weekday occurrence) whenever you need a run in every month. The picker warns you when the anchor you have chosen skips months.

Timezone

Cron expressions are evaluated in the workspace’s configured timezone, which defaults to UTC. To change it:

  1. Go to Settings > Workspace
  2. Set the Timezone to your preferred timezone
  3. Every schedule in the workspace that does not pin its own timezone will use it

An individual schedule can override the workspace default by prefixing its expression with CRON_TZ=<zone>, using an IANA zone name:

CRON_TZ=Europe/Berlin 0 9 L * *

The timezone is part of what a calendar anchor means — the last day of the month ends at a different instant in Berlin than in Los Angeles — so pin it explicitly on schedules whose exact firing instant matters.

Manual Only

No automatic schedule is set. The reverse ETL sync only runs when you explicitly trigger it via the UI or API.

When to use manual mode:

  • One-time data migrations
  • Ad-hoc data pushes
  • Testing and development
  • Reverse ETL syncs that should only run in response to external events

Triggering a manual run:

In the UI:

  1. Navigate to the reverse ETL sync detail page
  2. Click Run Now

Via the API:

curl -X POST https://composable.zeotap.com/api/v1/syncs/{sync_id}/trigger \ -H "Authorization: Bearer $API_TOKEN"

Schedule Configuration

Using the UI

When creating or editing a reverse ETL sync, the schedule step presents:

  1. Schedule type — Choose between Interval, Cron, or Manual
  2. Interval selector — (If interval) Choose from predefined intervals
  3. Cron expression — (If cron) Enter a cron expression
  4. Preview — Shows the next 5 scheduled run times based on your configuration

Using the API

# Interval schedule { "schedule": { "type": "interval", "interval_minutes": 60 } } # Cron schedule { "schedule": { "type": "cron", "cron_expression": "0 9 * * 1-5" } } # Manual only { "schedule": { "type": "manual" } }

Run Behavior

Concurrency

Reverse ETL sync runs for the same sync never overlap. If a scheduled run time arrives while the previous run is still executing, the new run is queued and starts immediately after the previous run completes.

Missed Runs

If a reverse ETL sync is paused and then resumed, missed scheduled runs are not retroactively executed. The sync resumes from the next upcoming scheduled time.

Run Duration

The total run duration depends on:

  • Query execution time in the warehouse
  • Number of records to process
  • Destination API rate limits and latency
  • Network conditions

For large reverse ETL syncs (100,000+ rows), consider scheduling during off-peak hours to avoid warehouse contention and destination API throttling.

Failure Handling

If a reverse ETL sync run fails:

  1. The failure is recorded in the run history
  2. The reverse ETL sync remains active — the next scheduled run proceeds as normal
  3. If multiple consecutive runs fail, Zeotap sends an alert to workspace administrators
  4. After a configurable number of consecutive failures, the reverse ETL sync may be automatically paused

Best Practices

Choosing the Right Frequency

Consider these factors when setting a schedule:

FactorRecommendation
Data freshness needsIf users need real-time data, use 15-30 minute intervals. For daily reports, daily is sufficient.
Data volumeLarger datasets take longer to query and sync. Allow enough time between runs for completion.
Destination API limitsSome destinations have daily or hourly API rate limits. Space reverse ETL syncs to stay within limits.
Warehouse costsEach reverse ETL sync run executes a query in your warehouse. More frequent syncs = more compute costs.
Business hoursIf data is only used during business hours, schedule syncs to refresh before the workday starts.

Staggering Syncs

If you have multiple reverse ETL syncs running against the same source, stagger their schedules to avoid overloading the warehouse:

# Instead of all at the top of the hour: Sync A: 0 * * * * (every hour at :00) Sync B: 0 * * * * (every hour at :00) ← concurrent load Sync C: 0 * * * * (every hour at :00) ← concurrent load # Stagger by 10 minutes: Sync A: 0 * * * * (every hour at :00) Sync B: 10 * * * * (every hour at :10) Sync C: 20 * * * * (every hour at :20)

Monitoring Schedule Health

Keep an eye on:

  • Run duration trends — If runs are getting slower, the dataset may be growing and the query needs optimization
  • Overlapping runs — If runs frequently overlap (next run queued because previous is still running), increase the interval or optimize the query
  • Failure rates — A sudden increase in failures may indicate a destination API issue or credential expiration

Next Steps

Last updated on