Scheduler

What It Is

The scheduler is Jetstack's time-based execution queue. It stores planned automation runs and processes them when their scheduled time arrives.

Unlike Types, Properties, or Modules, the scheduler is not primarily a design-time metadata resource. It is an operational surface. Its main purpose is to let you define when an automation should run, whether it should repeat, and whether the platform should keep an execution log.

Why It Matters

The scheduler is how you move work away from immediate user interaction and into time-based processing.

Use it when:

  • an action should happen later rather than now
  • a process should repeat on a cadence
  • you need reminders, follow-ups, escalations, or housekeeping
  • an automation should be triggered without a user opening a screen or clicking a button

Typical examples:

  • send a follow-up automation 3 days after record creation
  • repeat an automation every morning
  • retry a maintenance or reconciliation routine every hour
  • generate periodic digests

How To Read This Chapter

The scheduler has two layers:

  1. the task definition you create or store
  2. the queue behavior that the runtime applies when the task becomes due

This chapter explains both:

  • each task field and what it means
  • which fields are configurable in the scheduler screen
  • which fields exist mainly for API or automation-driven scheduling
  • what happens when a task is repeated, skipped, cancelled, or logged

Use this chapter together with:

Mental Model

Keep these distinctions clear:

  • a scheduler task points to one target automation
  • run_at defines the next planned execution time
  • next_run defines how the next occurrence is calculated after execution time arrives
  • last_run defines when recurrence should stop
  • skip suppresses execution of the current queued occurrence
  • log_runs controls whether execution details are written into the scheduler log
  • request stores the argument payload passed into the automation

The scheduler does not store business logic by itself. It stores timing and execution instructions for an automation that already exists elsewhere in the platform.

Scheduler Usage Modes

Jetstack uses the scheduler in two main ways.

Manual Scheduling From The Scheduler Screen

The scheduler screen lets an operator create a task by choosing:

  • an automation
  • the planned run time
  • optional recurrence
  • optional recurrence end time
  • whether logging should be enabled

This is the simplest operational path and is useful for:

  • ad hoc scheduling
  • testing a scheduled automation
  • operator-managed recurring jobs

Programmatic Scheduling From Automations Or API

The same scheduler can also be used from automation actions and platform API calls. In that mode, a task can be created with explicit argument payload in addition to the normal timing fields.

This matters because the stored task model is slightly richer than the form shown in the scheduler page. Some fields, such as the serialized request payload, may be populated by automations or API integrations even when the manual screen does not expose them directly.

Configuration Surface

The scheduler screen exposes the following task inputs when creating a new task:

OptionWhat it controlsHow to configure itNotes
automationWhich automation should run when the task becomes due.Select an automation from the list of available automations.Required.
run_atExact planned date and time for the first occurrence.Enter a date-time in the form field.Required. Stored as the queue time for this task.
next_runRelative recurrence definition for creating the next occurrence.Enter a PHP-compatible relative time expression such as +1 day or +1 week.Optional. If empty, the task runs once.
last_runEnd boundary for recurrence.Enter the latest allowed boundary for generating another occurrence.Optional. Used only when recurrence is enabled.
log_runsWhether executions should be written into the scheduler log.Check or uncheck the checkbox.Enabled by default in the form.

The stored task model also includes:

FieldPurposeHow it is populated
requestSerialized argument payload passed into the automation as scheduler arguments.Usually programmatically, not from the manual screen.
skipOne-time instruction to ignore execution of the queued occurrence.Set later through the scheduler screen action.
uuidStable task identifier.Generated automatically by the platform.
created_on, owner, created_byOperational metadata about task creation.Generated by the platform.

Configuration Options In Detail

automation

This selects the automation that the scheduler should execute.

How to configure it:

  • open the scheduler's new-task form
  • choose one automation from the select list

What it means:

  • the scheduler stores the automation ID in the task
  • when the task becomes due, the scheduler loads that automation and calls its runtime
  • the automation receives scheduler context including the stored task arguments

What to choose:

  • choose an automation that is intentionally built to run without an immediate UI action
  • scheduled automations are especially appropriate, but the scheduler can execute any automation that can run correctly from queued context

Practical guidance:

  • keep scheduled automations focused and deterministic
  • avoid choosing automations that depend on transient UI state unless they were designed for it
  • if the automation expects arguments, prefer scheduling it programmatically so the request payload is filled explicitly

run_at

This is the planned execution time of the current queued task.

How to configure it:

  • enter a date and time into the datetime-local field
  • the entered value is converted to a server-side date-time and stored as the due time

What it means:

  • the task becomes eligible for execution when the scheduler processes tasks with run_at earlier than the processing cutoff
  • the scheduler processes due tasks in ascending run_at order

Important behavior:

  • the scheduler page's "Run until now" action executes tasks due up to the current time
  • the background cron route also processes due tasks on a schedule
  • a task is not executed continuously at its exact timestamp on its own; it is executed the next time the scheduler runner processes due work

Use it for:

  • one-off delayed execution
  • the first occurrence of a recurring task

next_run

This field turns a one-time task into a recurring task.

How to configure it:

  • leave it empty for a one-time task
  • enter a relative time expression for recurrence, such as:
    • +1 hour
    • +1 day
    • +1 week
    • +1 month
    • next monday

What it means:

  • when a due task is processed, the scheduler calculates the next occurrence by taking the current task's run_at value and calling date-time modification logic with the next_run expression
  • the result becomes the run_at value of the next queued task

This is a very important detail:

  • recurrence is calculated from the current planned run time, not from the actual moment when the queue processor happened to run

That behavior helps avoid drift. For example:

  • task run_at = 2026-04-11 09:00
  • next_run = +1 day
  • if the runner processes the task at 09:04, the next task is still based on 09:00, not 09:04

Practical guidance:

  • use simple, explicit relative time expressions
  • avoid ambiguous text
  • prefer expressions whose meaning is obvious to future operators

Operational caution:

  • the scheduler form accepts next_run as free text
  • the runtime later interprets it through PHP date-time modification behavior
  • if the expression is invalid or unclear, recurrence may fail when the task is processed

last_run

This field defines the upper boundary for recurrence.

How to configure it:

  • leave it empty if the task should keep recurring without an end boundary
  • enter a date and time if recurrence should stop after a certain point

What it means:

  • when the current occurrence becomes due, the scheduler calculates the next occurrence using next_run
  • it only inserts that next task if the calculated next run is earlier than last_run

This means the boundary is effectively exclusive for the generated next occurrence.

Example:

  • run_at = 2026-04-11 09:00
  • next_run = +1 day
  • last_run = 2026-04-14 09:00

Generated next tasks:

  • 2026-04-12 09:00
  • 2026-04-13 09:00

Not generated:

  • 2026-04-14 09:00

because the scheduler checks whether the next planned run is strictly earlier than last_run.

Use last_run when:

  • a recurring reminder should stop after a fixed campaign window
  • a temporary maintenance loop should expire automatically
  • the scheduler should enforce a hard end date without requiring an operator to cancel the task manually

log_runs

This controls whether successful scheduler execution attempts are written to the scheduler log table.

How to configure it:

  • leave it checked to keep a run log
  • uncheck it for low-value, high-frequency, or noise-heavy tasks

What it means:

  • when enabled, the scheduler stores:
    • planned run time
    • actual execution time
    • automation ID
    • request payload
    • automation errors

What it does not do:

  • it does not change whether the automation runs
  • it does not control application-wide event logging
  • it does not automatically guarantee business-level observability beyond the scheduler log content

Use it for:

  • important recurring business processes
  • troubleshooting
  • tasks where operators need evidence of execution history

Disable it when:

  • the task is very frequent and the log would become noisy
  • failures are handled elsewhere and the scheduler log is not operationally useful

request

This is the stored payload of scheduler arguments passed into the automation at run time.

How to configure it:

  • the standard scheduler screen does not expose a dedicated form field for arguments
  • the field is normally populated when tasks are created from automations or API calls

What it means:

  • when the automation runs, the scheduler unserializes this payload and passes it into the automation as args
  • this is the main way to give a scheduled automation task-specific input

Use it when:

  • one automation should be scheduled many times with different parameters
  • the scheduled run must remember business context captured earlier
  • an automation schedules another automation for delayed execution

Example use cases:

  • schedule a reminder automation with a specific object ID
  • schedule a timeout follow-up with escalation metadata
  • schedule a digest job with a target audience or period definition

Queue Control Options After Creation

Once a task exists, the scheduler screen also lets an operator change how that queued occurrence is handled.

skip

This marks the queued occurrence so it will not be executed when it becomes due.

How to configure it:

  • use the Skip action in the scheduler list

What it means:

  • the task stays in the queue until it becomes due and is processed
  • when processed, the scheduler removes the current task and does not run its automation

Important recurring-task behavior:

  • recurrence is calculated before the current due task is discarded
  • this means skipping one occurrence of a recurring task normally skips only that occurrence
  • the next occurrence is still created if recurrence rules allow it

This is useful when:

  • you want to suppress one run without dismantling the recurring schedule
  • a planned run is no longer needed, but future runs should remain in place

Cancel Task

Cancel removes the queued task entirely.

How to configure it:

  • use the cancel action in the scheduler list

What it means:

  • the current queued record is deleted immediately
  • it will not be processed later

Difference from skip:

  • skip keeps the due occurrence in the queue until it is processed and then suppresses execution
  • cancel removes the occurrence right away

Use cancel when:

  • the task should disappear from the queue now
  • a scheduled run was created by mistake
  • the process should no longer continue in that queued form

Toggle Logging

The scheduler list also lets operators enable or disable logging for an already queued task.

How to configure it:

  • use the bell actions in the scheduler list

What it means:

  • the task record's log_runs flag is updated
  • future execution of that queued occurrence uses the new logging setting

This is useful when:

  • a task suddenly becomes operationally important
  • a noisy repeating task should stop producing scheduler log records

Execution Order And Runtime Behavior

When the scheduler processes due tasks, it performs the following steps:

  1. fetch tasks with run_at earlier than the chosen execution cutoff
  2. process them in ascending run_at order
  3. if recurrence exists, calculate and insert the next occurrence
  4. delete the current queued task
  5. if the current task is marked skip, stop there
  6. load the target automation
  7. pass scheduler arguments into the automation
  8. optionally log the run

This sequence has several important consequences.

Recurrence Is Prepared Before Current Execution

If a recurring task is due, the next occurrence is normally inserted before the current occurrence is executed.

That means:

  • a failure in the current automation does not automatically prevent the next occurrence from being created
  • recurring schedules behave like independent queued items, not like a single mutable timer

The Current Occurrence Is Removed During Processing

The current due task is deleted from the queue during processing.

That means:

  • there is no long-lived "same task instance" for a recurring series
  • each recurrence becomes a new queued task record

Scheduler Arguments Are Passed Into The Automation

The scheduler runs the automation with:

  • the application context
  • the unserialized args payload from the task

This is why scheduled automations can behave differently per task even when the underlying automation definition is the same.

Manual Runner Versus Background Runner

Jetstack exposes two practical ways to trigger scheduler processing.

Run Until Now

The scheduler page includes a manual run action.

Use it when:

  • testing a new scheduled setup
  • processing due tasks immediately during administration
  • verifying that a due automation behaves as expected

This action runs the scheduler up to the current moment.

Background Cron Processing

The scheduler presenter also exposes a route used by the tenant background process. Its purpose is broader than only the scheduler itself.

In addition to scheduled tasks, that run also processes:

  • due async automation timeouts
  • async upload housekeeping
  • cache cleanup

For documentation purposes, the important point is this:

  • the scheduler is part of the platform's operational background cycle, not an isolated utility page

Hidden And Internal Fields Worth Knowing

Most implementers only need the visible scheduler inputs, but a few internal fields are useful to understand.

uuid

Every scheduled task gets a UUID in addition to the numeric ID.

Why it matters:

  • UI actions such as skip, cancel, and logging toggles can target the task by UUID
  • integrations or tooling may prefer UUID-based references

schedule_definition_id

The scheduler table can also contain an internal schedule_definition_id used by implementation synchronization.

Why it matters:

  • not every scheduled task is purely ad hoc
  • some recurring scheduled records may be linked to synchronized implementation-level schedule definitions

For most tenant builders, this is background infrastructure rather than a field to configure directly in the scheduler page.

Common Scheduler Patterns

One-Time Delayed Task

Configure:

  • automation = target automation
  • run_at = desired future time
  • next_run = empty
  • last_run = empty

Use this for:

  • reminders
  • delayed notifications
  • future follow-up checks

Simple Daily Recurrence

Configure:

  • run_at = first planned daily run
  • next_run = +1 day
  • last_run = empty or set to an end date

Use this for:

  • daily sync
  • morning reports
  • recurring housekeeping

Finite Campaign Window

Configure:

  • run_at = first send time
  • next_run = recurrence step
  • last_run = final allowed boundary

Use this for:

  • temporary campaigns
  • time-boxed reminders
  • limited retry windows

Parameterized Delayed Execution

Configure through automation or API:

  • select automation
  • set args
  • set run_at
  • optionally set recurrence and log choice

Use this when:

  • the scheduled automation needs object-specific or case-specific input

Design Questions To Ask Before Scheduling

  • Should this happen immediately, or is delayed execution actually safer?
  • Does the target automation require explicit arguments?
  • Should this be a one-time delay or a recurring schedule?
  • Should the schedule stop automatically at a boundary?
  • Is logging important enough to justify the extra operational data?
  • If one occurrence is not needed, do you want to skip just that run or cancel the queued task entirely?

Best Practices

  • Use scheduled automations that are stable without UI context.
  • Keep next_run expressions simple and readable.
  • Use last_run for finite schedules instead of relying only on manual cancellation.
  • Turn on log_runs for business-critical jobs.
  • Use skip for one missed occurrence and cancel for removing the queued task itself.
  • Prefer programmatic scheduling when the automation needs argument payload.