Skip to content

Architecture

  • Jobs are registered at startup with a name and a delegate. Think of them as function definitions.
  • Runs are individual executions of a job. Each run tracks its status, arguments, result, logs, and timing.
  • Batches are grouped runs created by TriggerAllAsync and related APIs. A batch has a coordinator run and child runs.
  • Queues route jobs to specific worker pools with priority, concurrency limits, rate limiting, and pause/resume.
  • Nodes are your app instances. Each one runs scheduler and executor services that process runs.
  • Stores hold everything: jobs, runs, events, and node state. Surefire ships with in-memory, PostgreSQL, SQL Server, Redis, and SQLite stores.
  1. A run gets created, either from a cron schedule or a client call (TriggerAsync, RunAsync, TriggerAllAsync, etc.).
  2. A scheduler picks up the run on an available node.
  3. Your delegate executes. Logs, progress, and the result are captured along the way.
  4. The run status is updated and any subscribers (like the dashboard) are notified.

Surefire uses a pub/sub abstraction for real-time updates. In-memory notifications work in a single process. PostgreSQL and Redis providers include cross-node notifications.

ILogger output during job execution is captured per run and streamed live in the dashboard.

Stores keep job and run state. Every store implementation supports the same features. The in-memory store is great for development but loses everything when the process stops. For production, use one of the database-backed stores:

  • In-memory — default store with process-local persistence.
  • PostgreSQL — database-backed store with LISTEN/NOTIFY notifications.
  • SQL Server — database-backed store for SQL Server deployments.
  • Redis — Redis-backed store with Pub/Sub notifications.
  • SQLite — file-backed store.