Custom logic

Scheduled jobs that survive scale.

Schedule a job. Vadyl handles the distributed coordination — provider-native locks across instances, per-definition and per-project concurrency caps, real-RequestScope initialization for execution, retry with policy enforcement, abandoned-run recovery on restart. SkipIfRunning semantics; overlap policies; deterministic occurrence keys; canonical event emission for every run.

The triggers

Three canonical kinds. All durable.

Cron

Standard cron expressions. Time zone aware. Catch-up policy on missed fires (deterministic, configurable). Misfire windows fail closed past the policy.

Interval

Fixed-period firing. First-fire offset configurable. Drift correction so a daily 24h interval doesn't slowly walk forward.

One-shot

Single-occurrence triggers — schedule a follow-up two weeks from now, fire it once, mark complete. Resilient to host restarts.

Distributed locks

sp_getapplock on SQL Server, pg_advisory_lock on Postgres, GET_LOCK on MySQL. Provider-native, no external lock service. Per-definition + per-project + per-occurrence locks all coexist.

Concurrency caps

MaxConcurrentRunsPerDefinition + MaxConcurrentRunsPerProject. Both enforced atomically across scanner instances. Contention defers to the next scan cycle — no double dispatch.

Abandoned-run recovery

Crashed runs surface on restart. Recovery hosted service marks active phases Failed; paused phases left for the operator. Never loses canonical state on a host crash.

ServiceProfile authorization

Scheduled execution carries explicit identity through ServiceProfile. Authorization rules embedded in the profile — narrow, deny-by-default. The kernel sees a real ActorContext.

Real RequestScope init

Scheduled runs use IBackgroundScopeBootstrapper to fully initialize the request scope — project runtime, lifecycle, auth policy, project authorization. The handler sees the same scope shape an HTTP request would see.

Canonical event emission

Every run emits canonical events (TaskRunStarted, TaskRunSucceeded, TaskRunFailed) through the same outbox the rest of the platform uses. Subscribers integrate without bespoke channels.

3
Trigger kinds

Cron · Interval · One-shot

Provider-native
Distributed locks

sp_getapplock · pg_advisory_lock · GET_LOCK

Per-def + per-project
Concurrency caps

Both enforced atomically

Real
Background scope

Same shape as HTTP

Schedule a job. Walk away.

Distributed coordination. Concurrency caps. Crash-resilient. Real scope. Canonical events. The substrate handles every scheduling concern that fails subtly in production.