Skip to content

Scheduling & runs

Once a pipeline is deployed, the control plane executes it — on demand or on a schedule — over a durable, Postgres-backed job queue with a multi-worker pool.

valved serve runs the supervisor: the FastAPI app, the cron scheduler, the crash-recovery reaper, the archiver, and a worker pool.

Terminal window
valved serve # everything in one process
valved worker # or run standalone workers that drain the queue

Workers claim jobs with optimistic-claim semantics, emit heartbeats (so the reaper can reclaim a crashed worker’s jobs after a missed-heartbeat threshold), retry transient failures with backoff, and write structured per-run logs. Supervisor-loop intervals are tunable in valved/runtime.toml.

Terminal window
valved run <pipeline> --watch # enqueue a run and stream logs until it finishes
valved runs # recent runs (--limit, --pipeline)
valved runs --recovery <run_id> # render a run's recovery-attempt chain
valved logs <run_id> # logs for a specific run

You can also run just the extract-load (dlt) half of a pipeline:

Terminal window
valved el run <name> --watch
valved el verify <name> # schema + smoke test, no data load

The live schedule lives in the schedules table, and valved schedule changes it instantly — no code change, no PR. Every change is audited in schedule_changes and takes effect on the next scheduler tick.

Terminal window
valved schedule list
valved schedule show <pipeline>
valved schedule set-cron daily_revenue "0 3 * * *" --timezone America/New_York
valved schedule pause daily_revenue --reason "investigating upstream outage"
valved schedule resume daily_revenue

set-cron upserts: if the pipeline has no schedule row yet it creates one (at the prod target unless you pass --target-pipeline), so a schedule is stood up end to end from the CLI. Bad cron expressions and unknown IANA timezones are rejected up front, before anything is written.

A load that succeeds but is implausibly small never silently finalizes as a success. On every run, the runtime records per-resource actuals — rows loaded and each resource’s write disposition (replace / merge / append) — onto the run. After each successful load, it judges those actuals against an expectation:

  • First successful run — actuals are compared against the plan’s own row estimates (the ones valved plan printed).
  • Subsequent runs — actuals are compared against the previous successful run, disposition-aware: replace/merge resources are comparable run-over-run, but an append/incremental resource is never compared against prior totals — an incremental run legitimately loads a tiny fraction of the first load. Once it has history, an incremental resource is judged only by an explicitly declared min_rows floor.
  • Graceful degradation — no estimates and no history means the actuals are recorded but no judgment is made. Missing inputs never block a run.

The consequence is graduated:

  • Suspect — a moderate deviation (by default, actuals below half the expectation). The run still finalizes success, but it’s marked with a ⚠ suspect badge in valved runs and a durable run.suspect event is emitted per tripped resource.
  • Implausible — a high-confidence trip (by default, a ≥10× collapse in a replace/merge resource, or first-run actuals far below the estimate). The run finalizes failed with an error carrying the stable Implausible load prefix, and flows through the normal failure path: the schedule auto-pauses, an investigation records the diagnosis, and recovery classifies it as data-shaped — no automated code fix is attempted; check the source or extraction.

Thresholds, per-pipeline overrides, and the explicit opt-out live under [runner.plausibility] — see the configuration reference.

Every run, log line, status transition, and cost number is queryable from any surface — CLI, REST, MCP, or the static UI. External agents can subscribe to run-completion webhooks. Roll up cost and success/failure with:

Terminal window
valved metrics ... # token→USD cost, run success/failure, per-agent usage

When a scheduled run fails after exhausting retries, Valved’s recovery engine steps in — see Recovery.