Skip to content

Overlapping runs

Sometimes a task is started while its last run is still going: a slow run meets the next cron time, or someone clicks Run twice. on_overlap decides what happens.

[tasks.health-probe]
cron = "* * * * *"
on_overlap = "skip" # default is "queue"
run = "curl -sf https://example.com/health"

By default a task runs one copy at a time (max_concurrent is 1). While there is a free slot, a new run just starts. on_overlap only matters when all slots are taken.

The default. The new run waits and starts when the running one finishes. Runs start in the order they arrived, whether they came from cron, the CLI, the Web UI, or the API.

[tasks.process-uploads]
cron = "*/5 * * * *"
run = "/usr/local/bin/process"

Use it when every run has to happen eventually, for example when each run handles its own batch of work.

The queue has a limit, max_queued. When it’s full, the new run is recorded as queue_full and dropped. If you see queue_full runs, the task can’t keep up: run it less often, raise max_concurrent, or switch to skip.

The new run is dropped and recorded as skipped (exit code -1). The running one carries on.

[tasks.pg-dump]
cron = "0 * * * *"
on_overlap = "skip"
run = "pg_dump app > /backups/app.sql"

Use it when a missed run doesn’t matter (a probe, a poll) or when two copies at once would do harm (two dumps writing the same file).

By default a skipped run is not a failure, so it doesn’t send notifications and doesn’t count toward the failure rate (failures can add skipped to change that). It is never retried, whatever failures says. It still shows up in the history under its own status, so a task that keeps overlapping is easy to spot.

A manual start that gets skipped tells you so: the CLI, Web UI, and API report that the run was skipped.

RunWisp stops the oldest running run and starts the new one right away. The stopped run gets stop_signal and graceful_stop to exit, and is recorded as stopped, the same as a manual stop. A stopped run is never retried.

[tasks.rebuild-index]
on_overlap = "kill"
run = "/usr/local/bin/rebuild-index"

Use it when only the newest run matters: a rebuild or a deploy that the next request makes out of date.

Raise max_concurrent to let several runs of the same task go at once. on_overlap applies only once all of them are busy.

[tasks.thumbnail-render]
cron = "* * * * *"
max_concurrent = 4
run = "/usr/local/bin/render"

Here up to four renders run at the same time and a fifth waits in the queue. With on_overlap = "skip", the fifth is dropped instead.

Only raise it when the runs don’t share state or fight over one resource. It fits a task that usually finishes in seconds but sometimes takes much longer.

For a pool of long-running workers, use a service with instances instead. Services have no on_overlap; see Tasks and services.