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

    • Quartz 3 Quick Start
    • Tutorial
      • Using Quartz
      • Library Overview
      • Jobs And Triggers
      • More About Jobs
      • More About Triggers
      • 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
    • Frequently Asked Questions
    • Best Practices
    • Troubleshooting
    • API Documentation
    • Database Schema
    • 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
  • Unreleased Releases

    • Quartz 4.x
      • Quartz 4 Quick Start
      • Tutorial
        • Using Quartz
        • Jobs And Triggers
        • More About Jobs & JobDetails
        • More About Triggers
        • Simple Triggers
        • Cron Triggers
        • RecurrenceTrigger
        • Trigger and Job Listeners
        • Scheduler Listeners
        • Job Stores
        • Configuration, Resource Usage and SchedulerFactory
        • Advanced (Enterprise) Features
        • Miscellaneous Features
        • CronTrigger Tutorial
      • Configuration Reference
      • Migration Guide
      • Troubleshooting
      • API Documentation
      • How To's

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

        • Quartz Core Additions

          • Dashboard
          • Jobs
          • JSON Serialization
          • Plugins
        • Integrations

          • ASP.NET Core Integration
          • HTTP API
          • 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

JSON Configuration

Quartz.NET supports hierarchical JSON configuration in appsettings.json, providing a modern alternative to flat property keys. This includes both scheduler properties and declarative job/trigger definitions.

Tips

Requires Quartz 4.1 or later. JSON configuration support is included in the core Quartz package.

Hierarchical Properties

Instead of flat property keys like "quartz.threadPool.maxConcurrency": "10", you can use a natural nested JSON structure:

{
  "Quartz": {
    "Scheduler": {
      "InstanceName": "My Scheduler",
      "InstanceId": "AUTO"
    },
    "ThreadPool": {
      "MaxConcurrency": 10
    },
    "JobStore": {
      "Type": "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",
      "DataSource": "default",
      "TablePrefix": "QRTZ_"
    },
    "DataSource": {
      "default": {
        "Provider": "SqlServer",
        "ConnectionString": "Server=localhost;Database=quartznet"
      }
    },
    "Plugin": {
      "jobHistory": {
        "Type": "Quartz.Plugin.History.LoggingJobHistoryPlugin, Quartz.Plugins"
      }
    },
    "Serializer": {
      "Type": "stj"
    }
  }
}

Mapping Rules

Each JSON path segment becomes a dot-separated segment in the flat property key, with PascalCase automatically converted to camelCase:

JSON PathFlat Property Key
Scheduler:InstanceNamequartz.scheduler.instanceName
ThreadPool:MaxConcurrencyquartz.threadPool.maxConcurrency
DataSource:default:Providerquartz.dataSource.default.provider
Plugin:jobHistory:Typequartz.plugin.jobHistory.type

Usage with DI

services.AddQuartz(Configuration.GetSection("Quartz"), q =>
{
    // Additional code-based configuration still works alongside JSON
    q.AddJob<MyJob>(j => j.WithIdentity("codeJob").StoreDurably());
});

Usage without DI

var properties = QuartzConfigurationHelper.ToNameValueCollection(
    Configuration.GetSection("Quartz"));
var factory = new StdSchedulerFactory();
factory.Initialize(properties);

Backward Compatibility

Flat property keys still work. You can mix both styles in the same section:

{
  "Quartz": {
    "quartz.scheduler.instanceId": "AUTO",
    "ThreadPool": {
      "MaxConcurrency": 10
    }
  }
}

JSON Scheduling Data

Jobs and triggers can be defined declaratively in appsettings.json under a Schedule sub-section:

{
  "Quartz": {
    "Scheduler": {
      "InstanceName": "My Scheduler"
    },
    "Schedule": {
      "Jobs": [
        {
          "Name": "sampleJob",
          "Group": "sampleGroup",
          "JobType": "MyApp.Jobs.SampleJob, MyApp",
          "Description": "A sample job",
          "Durable": true,
          "Recover": false,
          "JobDataMap": {
            "connectionString": "Server=localhost",
            "retryCount": "3"
          }
        }
      ],
      "Triggers": [
        {
          "Name": "cronTrigger",
          "JobName": "sampleJob",
          "JobGroup": "sampleGroup",
          "Description": "Fires every 10 seconds",
          "Cron": {
            "Expression": "0/10 * * * * ?",
            "TimeZone": "UTC"
          }
        }
      ]
    }
  }
}

Trigger Types

Exactly one schedule type must be specified per trigger. The trigger type is determined by which nested object is present.

Simple Trigger

{
  "Name": "simpleTrigger",
  "JobName": "myJob",
  "Simple": {
    "RepeatCount": -1,
    "Interval": "00:00:10",
    "MisfireInstruction": "SmartPolicy"
  }
}
  • RepeatCount: Number of times to repeat. Use -1 for indefinite, 0 for fire once.
  • Interval: TimeSpan string (e.g., "00:00:10" for 10 seconds, "01:00:00" for 1 hour).

Cron Trigger

{
  "Name": "cronTrigger",
  "JobName": "myJob",
  "Cron": {
    "Expression": "0/30 * * * * ?",
    "TimeZone": "America/New_York",
    "MisfireInstruction": "DoNothing"
  }
}

Calendar Interval Trigger

{
  "Name": "calendarTrigger",
  "JobName": "myJob",
  "CalendarInterval": {
    "RepeatInterval": 1,
    "RepeatIntervalUnit": "Day",
    "MisfireInstruction": "SmartPolicy"
  }
}

RepeatIntervalUnit values: Second, Minute, Hour, Day, Week, Month, Year.

Daily Time Interval Trigger

{
  "Name": "businessHoursTrigger",
  "JobName": "myJob",
  "DailyTimeInterval": {
    "RepeatInterval": 15,
    "RepeatIntervalUnit": "Minute",
    "RepeatCount": -1,
    "StartTimeOfDay": "08:00:00",
    "EndTimeOfDay": "17:00:00",
    "DaysOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
    "TimeZone": "America/Chicago"
  }
}

Common Trigger Fields

All trigger types support these optional fields:

FieldDescription
NameTrigger name (required)
GroupTrigger group (defaults to DEFAULT)
JobNameAssociated job name (required)
JobGroupAssociated job group (defaults to DEFAULT)
DescriptionTrigger description
PriorityTrigger priority (integer)
CalendarNameCalendar to apply
StartTimeISO 8601 start time (e.g., "2024-01-01T00:00:00Z")
StartTimeSecondsInFutureStart time as seconds from now (mutually exclusive with StartTime)
EndTimeISO 8601 end time
JobDataMapKey-value pairs for the trigger's data map

Multiple Named Schedulers

When the Quartz section contains a Schedulers sub-section, each child is automatically registered as a named scheduler:

{
  "Quartz": {
    "Schedulers": {
      "Primary": {
        "Scheduler": {
          "InstanceId": "AUTO"
        },
        "ThreadPool": {
          "MaxConcurrency": 10
        },
        "Schedule": {
          "Jobs": [
            {
              "Name": "primaryJob",
              "JobType": "MyApp.Jobs.PrimaryJob, MyApp",
              "Durable": true
            }
          ],
          "Triggers": [
            {
              "Name": "primaryTrigger",
              "JobName": "primaryJob",
              "Cron": { "Expression": "0/10 * * * * ?" }
            }
          ]
        }
      },
      "Secondary": {
        "ThreadPool": {
          "MaxConcurrency": 5
        }
      }
    }
  }
}
// Registers "Primary" and "Secondary" named schedulers automatically
services.AddQuartz(Configuration.GetSection("Quartz"));
services.AddQuartzHostedService();

Each named scheduler section supports the same hierarchical properties, Schedule sub-section with Jobs/Triggers, and code-based overrides.

Warning

Defining both a Schedulers sub-section and direct scheduler configuration (e.g., Scheduler, ThreadPool at the top level) is an error. Use one or the other.

Standalone JSON Files (quartz_jobs.json)

For file-based scheduling with hot-reload support, use JsonSchedulingDataProcessorPlugin from the Quartz.Plugins package. See Quartz Plugins for plugin configuration.

Standalone JSON files use the same Jobs and Triggers format as the Schedule section above, wrapped in an envelope with optional PreProcessingCommands and ProcessingDirectives:

{
  "PreProcessingCommands": {
    "DeleteJobsInGroup": ["obsoleteGroup"],
    "DeleteTriggersInGroup": ["oldTriggerGroup"],
    "DeleteJobs": [
      { "Name": "oldJob", "Group": "DEFAULT" }
    ],
    "DeleteTriggers": [
      { "Name": "oldTrigger" }
    ]
  },
  "ProcessingDirectives": {
    "OverWriteExistingData": true,
    "IgnoreDuplicates": false,
    "ScheduleTriggerRelativeToReplacedTrigger": false
  },
  "Schedule": {
    "Jobs": [
      {
        "Name": "myJob",
        "JobType": "MyApp.Jobs.MyJob, MyApp",
        "Durable": true
      }
    ],
    "Triggers": [
      {
        "Name": "myTrigger",
        "JobName": "myJob",
        "Cron": {
          "Expression": "0/30 * * * * ?"
        }
      }
    ]
  }
}

PreProcessingCommands

Commands executed before scheduling. All fields are optional:

FieldDescription
DeleteJobsInGroupArray of group names. Use "*" to delete jobs in all groups.
DeleteTriggersInGroupArray of group names. Use "*" to delete triggers in all groups.
DeleteJobsArray of { "Name": "...", "Group": "..." } objects. Group is optional.
DeleteTriggersArray of { "Name": "...", "Group": "..." } objects. Group is optional.

ProcessingDirectives

FieldDefaultDescription
OverWriteExistingDatatrueReplace existing jobs/triggers with the same identity.
IgnoreDuplicatesfalseWhen OverWriteExistingData is false, silently skip duplicates instead of erroring.
ScheduleTriggerRelativeToReplacedTriggerfalseAdjust new trigger timing based on old trigger's last fire time.
Help us by improving this page!
Last Updated: 5/9/26, 5:02 AM
Contributors: dependabot[bot]