Quartz.NETQuartz.NET
Home
Features
Blog
Discussions
NuGet
GitHub
Home
Features
Blog
Discussions
NuGet
GitHub
  • Getting Started

    • Overview
    • Quartz 4 Quick Start
    • Tutorial
      • Using Quartz
      • Jobs And Triggers
      • More About Jobs & JobDetails
      • Job Data
      • More About Triggers
      • Querying Jobs and Triggers
      • Simple Triggers
      • Cron Triggers
      • RecurrenceTrigger
      • Time and TimeProvider
      • Trigger and Job Listeners
      • Scheduler Listeners
      • Job Execution Middleware
      • Job Stores
      • Configuration, Resource Usage and Building a Scheduler
      • Building a Scheduler Without a Host
      • Clustering
      • Execution Groups
      • Node Affinity (Preferred Node)
      • Testing
    • Configuration Reference
    • JSON Configuration
    • Cron Expression Reference
    • Multi-Tenancy
    • Frequently Asked Questions
    • Best Practices
    • Before You Go Live
    • Operating a Cluster
    • Log Events
    • Tenancy Patterns
    • Database Schema
    • Database Schema Changes
    • Migration Guide
    • Troubleshooting
    • API Documentation
  • How To's
    • One-Off Job
    • Rescheduling Jobs
    • Retrying Failed Jobs
    • Multiple Triggers
    • Job Template
    • Running Quartz under Aspire
    • Quartz.NET with Wolverine
    • Embedding Quartz in a Library
    • Running under an External Leader Election
    • Publishing Trimmed and Native AOT
    • Extending Quartz: what is open, what is closed, and how to ask
    • A Job Store of Your Own
    • A Driver Delegate for a New Database
    • Persisting a Custom Trigger Type
    • A Lock Handler of Your Own
  • Packages

    • Quartz Core Additions

      • Jobs
      • Serialization (System.Text.Json)
      • JSON Serialization
      • Plugins
    • Integrations

      • Aspire Integration
      • ASP.NET Core Integration
      • HTTP API
      • HTTP Client
      • Dashboard
      • Hosted Services Integration
      • Microsoft DI Integration
      • Multiple Schedulers with Microsoft DI
      • Observability
      • Redis Lock Handler
      • TimeZoneConverter Integration
    • 3rd Party Plugins for Quartz
  • Quartz 3.x

    • Getting Started

      • Quartz 3 Quick Start
      • Tutorial
        • Using Quartz
        • Library Overview
        • Jobs And Triggers
        • More About Jobs
        • More About Triggers
        • Execution Groups
        • Node Affinity (Preferred Node)
        • Simple Triggers
        • Cron Triggers
        • RecurrenceTrigger
        • Trigger and Job Listeners
        • Scheduler Listeners
        • Job Stores
        • Tuning the Scheduler
        • Configuration, Resource Usage and SchedulerFactory
        • Advanced (Enterprise) Features
      • Configuration Reference
      • JSON Configuration
      • Multi-Tenancy
      • Frequently Asked Questions
      • Best Practices
      • Tenancy Patterns
      • Troubleshooting
      • API Documentation
      • Database Schema
      • Database Schema Changes
      • Migration Guide
      • Miscellaneous Features
    • How To's

      • One-Off Job
      • Multiple Triggers
      • Job Template
      • Using the CronTrigger
      • Rescheduling Jobs
    • Packages

      • Quartz Core Additions

        • Dashboard
        • Jobs
        • Serialization (System.Text.Json)
        • Serialization (Newtonsoft Json.NET)
        • Plugins
      • Integrations

        • ASP.NET Core Integration
        • Hosted Services Integration
        • Microsoft DI Integration
        • Multiple Schedulers with Microsoft DI
        • OpenTelemetry Integration
        • OpenTracing Integration
        • Redis Lock Handler
        • TimeZoneConverter Integration
      • 3rd Party Plugins for Quartz
  • Old Releases

    • Quartz 2.x
      • Quartz 2 Quick Start
      • Tutorial
        • Lesson 1: Using Quartz
        • Lesson 2: Jobs And Triggers
        • Lesson 3: More About Jobs & JobDetails
        • Lesson 4: More About Triggers
        • Lesson 5: SimpleTrigger
        • Lesson 6: CronTrigger
        • Lesson 7: TriggerListeners and JobListeners
        • Lesson 8: SchedulerListeners
        • Lesson 9: JobStores
        • Lesson 10: Configuration, Resource Usage and SchedulerFactory
        • Lesson 11: Advanced (Enterprise) Features
        • Lesson 12: Miscellaneous Features of Quartz
        • CronTrigger Tutorial
      • Configuration Reference
      • Migration Guide
      • API Documentation
    • Quartz 1.x
      • Tutorial
        • Lesson 1: Using Quartz
        • Lesson 2: Jobs And Triggers
        • Lesson 3: More About Jobs & JobDetails
        • Lesson 4: More About Triggers
        • Lesson 5: SimpleTrigger
        • Lesson 6: CronTrigger
        • Lesson 7: TriggerListeners and JobListeners
        • Lesson 8: SchedulerListeners
        • Lesson 9: JobStores
        • Lesson 10: Configuration, Resource Usage and SchedulerFactory
        • Lesson 11: Advanced (Enterprise) Features
        • Lesson 12: Miscellaneous Features of Quartz
      • API Documentation
  • License

Quartz.AspNetCore provides integration with ASP.NET Core hosted services.

Tips

If you only need the generic host, generic host integration might suffice.

Installation

You need to add NuGet package reference to your project which uses Quartz.

dotnet add package Quartz.AspNetCore

Using

You can host the scheduler by invoking AddQuartzHostedService on the web application builder. This adds a hosted Quartz server into the ASP.NET Core process that is started and stopped based on the application's lifetime.

Tips

AddQuartzHostedService lives in the core Quartz package, and so does the health check. Quartz 3's AddQuartzServer, which registered the hosted service and a health check together, is gone — call each by its own name.

Tips

See Quartz documentation to learn more about configuring Quartz scheduler, jobs and triggers.

Example Program.cs configuration

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

builder.AddQuartz(q =>
{
    // base Quartz scheduler, job and trigger configuration
});

// ASP.NET Core hosting
builder.AddQuartzHostedService(options =>
{
    // when shutting down we want jobs to complete gracefully
    options.WaitForJobsToComplete = true;
});

WebApplication app = builder.Build();

A practical example of the setup

In the code below you can see a real application of the Quartz package within ASP.NET Core MVC.

To better illustrate the use of the Quartz library, imagine you have a Program.cs file that is always created when you choose the MVC architecture, and then imagine a Jobs folder where you have all the tasks you want Quartz to perform in the background when you run your web application.

After that, it's pretty straightforward.

In the Jobs folder, you create a class that will perform the tasks you specify. The class should extend the IJob interface and implement the Execute method.

Example SendEmailJob.cs configuration

public sealed class SendEmailJob : IJob
{
    private readonly IEmailSender sender;

    public SendEmailJob(IEmailSender sender)
    {
        this.sender = sender;
    }

    public ValueTask Execute(IJobExecutionContext context, CancellationToken cancellationToken = default)
    {
        // Code that sends a periodic email to the user (for example)
        return sender.SendDigest(cancellationToken);
    }
}

A job whose work is asynchronous is written async ValueTask as usual. One that only forwards a call, like this one, can return it directly and skip the state machine; one with nothing to await at all returns default, which is a completed ValueTask that allocates nothing. What a job must not do is block: the scheduler is holding a worker slot for it.

After that, you just need to build Quartz trigger in Program.cs, which guarantees that the job will run according to the preset interval.

One job with one trigger is what ScheduleJob<TJob> is for: it registers the job, builds the trigger, and names the job after the trigger, so there is no JobKey to declare and no ForJob to keep in step. A job that several triggers share is registered with AddJob and given each trigger with AddTrigger — see Microsoft DI Integration.

Example Program.cs configuration

builder.AddQuartz(q =>
{
    // One job and the one trigger that fires it. The job class you wrote in the
    // Jobs folder is the type argument; the job takes its identity from the trigger.
    q.ScheduleJob<SendEmailJob>(trigger => trigger
        .WithIdentity("SendEmailJob-trigger")
        // This Cron interval can be described as "run every minute" (when second is zero)
        .WithCronSchedule("0 * * ? * *"));
});

builder.AddQuartzHostedService(options => options.WaitForJobsToComplete = true);

For more on cron triggers see the CronTriggers lesson, and for the expression syntax itself the Cron Expression Reference.

Health checks

The scheduler's health check is in the core Quartz package rather than this one. It reads IScheduler.Status and probes the job store, and needs nothing from ASP.NET Core to do either — so registering it, naming it, and choosing which probes it belongs to are all covered by Hosted Services Integration.

What this package's framework adds is the endpoint that serves the report, and the mapping from a status to a response code:

app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
    Predicate = registration => registration.Tags.Contains("ready")
});

Degraded maps to 200 by default, exactly as Healthy does, so a scheduler in standby looks healthy to anything that reads only the status code. Map it to 503 in HealthCheckOptions.ResultStatusCodes if a standby node should leave the rotation.

Help us by improving this page!
Last Updated: 9/10/26, 8:50 AM
Contributors: Marko Lahma, Claude Opus 5 (1M context)
Prev
Aspire Integration
Next
HTTP API