Spindle DocsStart a trial

Job orchestration

Your cron jobs grew up. Give them a graph.

Spindle replaces scattered crontabs and one-off CI jobs with a single scheduler: jobs declare what they depend on, Spindle decides what runs when, retries what failed, and tells you before a late run becomes an incident.

  • Schedules in plain cron syntax or as an interval — plus event and manual triggers.
  • Dependencies between steps, so a report never reads a half-finished table.
  • Retries with backoff per step, not blunt retries of the whole pipeline.
  • Agents run in your own network; Spindle never needs inbound access to your boxes.

Read the quickstart   See what's included →

A workflow, start to finish

Three steps, one schedule. The export waits for both loaders; if either one fails, the export is not attempted and nobody gets a wrong number.

load-orders1m 12s load-refunds48s build-exportrunning notify-financequeued

Where it runs

Control plane in Frankfurt and Amsterdam, with a cold standby in Helsinki. Data stays in the EU; agents hold your credentials and Spindle only ever sees step names, timings and exit codes.


What teams use it for

Nightly data loads

The classic case. Twelve extracts that must finish before the warehouse rebuild starts, and a rebuild that must not start twice.

Billing and invoicing runs

Jobs that cannot be retried blindly. Spindle keeps per-step idempotency keys so a retry of step four does not re-charge anyone.

Housekeeping

Backups, log rotation, certificate renewals, cache warms. Boring work that is only visible when it silently stops happening.

4,100+workflows scheduled
19Mstep runs per month
99.95%scheduler availability
220 msmedian trigger latency

A workflow is a file

Workflows live in your repository next to the code they run. Spindle picks up the definition from a Git ref or from the CLI, so a change to a schedule goes through the same review as any other change.

# spindle.yaml
workflow: warehouse-nightly
schedule: "20 2 * * *"      # 02:20, agent timezone
timezone: Europe/Amsterdam
late_after: 45m              # alert if not finished by then

steps:
  - name: load-orders
    run: "./bin/extract orders"
    retries: { max: 3, backoff: 30s }

  - name: load-refunds
    run: "./bin/extract refunds"
    retries: { max: 3, backoff: 30s }

  - name: build-export
    needs: [load-orders, load-refunds]
    run: "./bin/export --day=$SPINDLE_RUN_DATE"
    timeout: 20m

Everything else — history, logs, the dependency graph, the alert when build-export is still running at 03:05 — comes from that file without extra configuration.

Recent runs

warehouse-nightly
RunDurationResult
#41926m 41spassed
#41917m 02spassed
#419031m 18slate
#41896m 55spassed
#41882m 09sfailed
#41876m 38spassed
Run #4190 was late, not broken. The upstream database was in a long vacuum; load-orders retried twice and then succeeded. Spindle paged on the late_after budget, not on a failure that never happened.

Integrations

Alerts to Slack, Mattermost, PagerDuty, Opsgenie or a plain webhook. Metrics in Prometheus format from the agent, run history over the REST API.


We had forty-one crontabs across nine hosts and no idea which of them mattered. Moving them into Spindle took a week, and the first thing it found was two jobs that had been failing quietly since March. Platform lead, logistics company, Utrecht

Try it on one workflow

Install the agent, point it at a repository, move your noisiest cron job over. Trial accounts keep full history for 14 days and need no payment details.

Quickstart →  ·  Plans and limits →  ·  Talk to us →