Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Version Migrations for Background Jobs: BackgroundService Changes from .NET 6 to 10, .NET 11 and Quartz 3→4
.NET 6 started stopping the host on a BackgroundService failure, ShutdownTimeout went from 5 to 30 seconds in .NET 7, .NET 8 brought lifecycle hooks, and .NET 10 moved all of ExecuteAsync to the background: an exception before the first await crashes the process with code 134 on .NET 8 but is logged and exits with 0 on .NET 10. In Quartz 3→4 a simple job gave a single CS0535 error; the real work is packages, the schema migration and changed defaults.
Scheduling with Quartz.NET 4: Jobs, Triggers, Persistent JobStore and Clustering
In Quartz.NET 4, jobs and triggers are separate objects, IJob returns ValueTask and takes a CancellationToken, and DI and hosting live in the core Quartz package. Two nodes sharing one PostgreSQL database form a cluster: when the executing node dies by kill -9, the other notices about 15 seconds later and reruns the RequestRecovery job with recovering=true. At startup the code definition overwrites the JobDataMap stored in the database; IgnoreDuplicates prevents that.
Cron Expressions: Unix 5-Field, 6-Field with Seconds, Quartz Format and Time Zone/DST Pitfalls
Unix cron has 5 fields, Quartz wants 6–7 fields starting with seconds and counts weekdays as 1=Sunday; Quartz 4 rejects "0 0 * * *" with the default parser and accepts it with CronFormat.Unix. Across DST, a daily 02:30 job runs once at 03:00 in spring and only once in autumn, while interval jobs run twice in the repeated hour. You can write your own cron scheduler on TimeProvider and test it with FakeTimeProvider.
Running Work Outside the Request: Choosing Between Fire-and-Forget, BackgroundService, Hangfire and Quartz.NET
Work started with Task.Run inside a controller loses its DbContext when the request scope ends, swallows its exception silently and dies halfway through a deploy; it has to be handed to something the host manages. Five questions drive the choice: can the work be lost on restart, is it scheduled, do you need retries and a dashboard, how many instances run; the answers point to BackgroundService, Hangfire, Quartz.NET or a platform scheduler.