Rule schedule — when rules run
Last updated: May 19, 2026
Rule schedule — when rules run
Rules support two schedule types: interval (every N minutes, min 15) and daily_at_time (extensions — once per day at HH:MM in workspace timezone, with day-parting). Underneath, a cron in apps/backend/src/server.ts fires every 15 minutes (with 2-minute offset) and selects rules where last_evaluated_at < 15 min ago. Sub-15-min cadence is not supported by design.
Who is this for
Anyone choosing how often a rule should evaluate. Reference for the builder's schedule picker.
The two schedule types
interval
Rule evaluates every N minutes. Field: interval_minutes.
Minimum: 15 (aligned to cron cadence)
Maximum: 1440 (24 hours)
Most common choice. Good for continuous monitoring rules (kill losers, scale winners, protect spend).
daily_at_time
Rule evaluates once per day at a specific time, plus day-parting filters. Requires DayPartingConfig:
days_of_week: array of 0-6 (Sun-Sat)hours_of_day: array of 0-23timezone: IANA timezone stringtype:"day_parting"
Available as part of the Rules Engine extensions. Use case: end-of-day kill, start-of-week scale, time-of-day budget shifts.
Preset day-parting templates available:
work— Mon-Fri, 9-18night— all days, 22-5clear— disabled
The underlying cron
Independent of schedule type, a single cron handles all rules:
Fires every 15 minutes with a 2-minute offset (i.e. at HH:02, HH:17, HH:32, HH:47)
Queries
automation_ruletable for rules where:status = activelast_evaluated_atis null OR more than 15 minutes ago (interval rules)For
daily_at_timerules: current time matches the schedule
Updates
last_evaluated_at = now()for each selected rule before enqueueing (prevents cascade duplicates if cron tick overlaps SQS processing)Enqueues to SYNC SQS queue (50 max in-flight, 15-min visibility timeout, 20 max attempts, 30s base backoff)
Why 15 min and not faster: protects against runaway rule loops + respects platform API rate limits + post-conversion data settles every 5-15 min.
interval_minutes = 15 vs 30 vs 60
A rule with interval_minutes: 15 evaluates at the next cron tick after 15 min from last_evaluated_at. Cron runs every 15 min, so cadence is exactly 15 min in steady state.
A rule with interval_minutes: 30 evaluates every 30 min (cron skips it on alternate ticks).
A rule with interval_minutes: 60: every hour.
Pick based on:
Fast metrics (spend, CTR, frequency) — 15 or 30 min
Slow metrics (postback ROAS / CPA) — 60+ min; data doesn't move faster anyway
Daily decisions — use
daily_at_timeinstead
Workspace timezone
daily_at_time schedules + day-parting use the workspace timezone (see team-106 Workspace Defaults). Verify timezone is correct before saving — wrong timezone = rule fires at unexpected local time.
What you'll see
In the rule list /rules:
Column Next fire — when the rule will next evaluate (computed from
last_evaluated_at + interval_minutes)Column Last fired —
last_evaluated_atvalue
In rule detail /rules/:id:
Schedule summary at top: "Every 30 minutes" or "Daily at 09:00 (Europe/Rome)"
Execution timeline showing actual fire times
Schedule + cooldown interaction
Schedule and cooldown are separate concerns:
Schedule = when the rule evaluates
Cooldown = how long after acting on an entity before re-acting on the same entity
A rule with interval_minutes: 15 and cooldown_minutes: 360 evaluates every 15 min, but won't re-pause the same adset within 6 hours of pausing it. Other entities can still be acted on at next 15-min evaluation.
See rul-108 protections.
Common mistakes
Setting interval_minutes: 5: rejected — min is 15
Wrong timezone on daily_at_time: rule fires at wrong wall-clock time. Verify workspace timezone first.
Expecting real-time reaction: cron is every 15 min minimum. For real-time alerts on critical issues, use Sentry / monitoring outside Wevion.
interval_minutes: 1440 with cooldown 720: rule evaluates once per day but cooldown allows multiple actions within the day — possibly confusing. Match cadence to intent.
Related
Protections + cooldown — how protections interact with schedule
Extensions — daily_at_time + day-parting details
Workspace defaults — timezone source