[{"data":1,"prerenderedAt":138},["ShallowReactive",2],{"post-\u002Fblog\u002Flocal-job":3},{"id":4,"title":5,"body":6,"book":126,"date":127,"description":128,"extension":129,"meta":130,"navigation":131,"path":132,"seo":133,"stem":134,"tags":135,"__hash__":137},"blog\u002Fblog\u002Flocal-job.md",".NET LocalJob",{"type":7,"value":8,"toc":119},"minimark",[9,14,24,27,34,38,41,44,80,83,87],[10,11,13],"h2",{"id":12},"background","Background",[15,16,17,18,23],"p",{},"This is a counterpart to ",[19,20,22],"a",{"href":21},"\u002Fblog\u002Fwhy-i-built-singletonjob","SingletonJob"," where the job runs on every instance of your app. It's much simpler, since there's no Redis, no database, no coordination, and none of the trouble that comes with them.",[15,25,26],{},"You can find the package here:",[15,28,29],{},[19,30,31],{"href":31,"rel":32},"https:\u002F\u002Fgithub.com\u002Fhaiilong\u002FLocalJob",[33],"nofollow",[10,35,37],{"id":36},"why-this-exists","Why this exists",[15,39,40],{},"Some background work belongs to the process, not to the deployment: flushing a local metrics buffer, trimming this pod's temp directory, pinging a keep-alive, draining an in-memory queue.",[15,42,43],{},"You can already do this with Quartz or a plain .NET background service, but I wanted a few more things:",[45,46,47,51,54],"ol",{},[48,49,50],"li",{},"Easier to create new jobs (Auto-discovery, templates, etc.)",[48,52,53],{},"Easy to configure (polling interval, isEnabled?, ExecutionTimeout, etc.)",[48,55,56,57],{},"Features that are not well supported today:\n",[45,58,59,62,65,68,71,74,77],{},[48,60,61],{},"Overlap protection",[48,63,64],{},"Misfire handling",[48,66,67],{},"Graceful shutdown",[48,69,70],{},"Error handling that doesn't kill the loop",[48,72,73],{},"Per-job Configuration",[48,75,76],{},"RunOnStartup (for IntervalJob)",[48,78,79],{},"Jitter (so that jobs don't hit your DB at the same time)",[15,81,82],{},"Take a look at the README and the sample project. It's easy to use and powerful enough.",[10,84,86],{"id":85},"differences-from-singletonjob","Differences from SingletonJob",[45,88,89,92,108],{},[48,90,91],{},"No Redis, leader election, or anything related, so it's a lot simpler while keeping the same API shape",[48,93,94,95,99,100,103,104,107],{},"Per-job settings live on the job class, not in ",[96,97,98],"code",{},"Program.cs",". Override ",[96,101,102],{},"ConfigureJobOptions","; it receives the job's private copy of the options and runs last, after ",[96,105,106],{},"appsettings.json",". Since LocalJob is all in-process, the job class is the natural home for its config, while a lot of SingletonJob's configuration feels more like an operations concern",[48,109,110,111,114,115,118],{},"With no name-keyed config, an ",[96,112,113],{},"IOptionsFactory\u003CLocalJobOptions>"," constructor parameter would be overkill, so it takes ",[96,116,117],{},"IOptions\u003C>"," instead.",{"title":120,"searchDepth":121,"depth":121,"links":122},"",2,[123,124,125],{"id":12,"depth":121,"text":13},{"id":36,"depth":121,"text":37},{"id":85,"depth":121,"text":86},null,"2026-07-14","In-memory recurring background jobs for dotnet.","md",{},true,"\u002Fblog\u002Flocal-job",{"title":5,"description":128},"blog\u002Flocal-job",[136],"tech","GEI-gZXjwnRNTRDHa-qZ1s5wKyWoMm1FGAUfMSkCOvw",1792143571345]