---
title: Recurring Jobs
description: Runtime recurring schedule administration operations.
order: 63
---

# Recurring Jobs

Use recurring attributes for schedule definition and `IDurableScheduleAdminService` for runtime schedule operations.

## Define a recurring job

```csharp
using DurableStack.Core.Abstractions;
using DurableStack.Hosting.DependencyInjection;

[DurableJob(Name = "daily-reconciliation", MaxAttempts = 4)]
[RecurringJob("0 2 * * *", TimeZone = "UTC", Enabled = true, AllowConcurrentRuns = false)]
public sealed class DailyReconciliationJob : IDurableJob
{
    public Task ExecuteAsync(JobContext context, CancellationToken cancellationToken = default)
        => Task.CompletedTask;
}
```

## Supported operations

- list all schedules (`includeDisabled` optional)
- disable or enable by schedule name
- run schedule now (ad-hoc enqueue)
- update cron expression and time zone

## Service usage

```csharp
var scheduledJobs = await scheduleAdmin.ListScheduledJobsAsync(includeDisabled: true, cancellationToken);

var disabled = await scheduleAdmin.SetScheduledJobEnabledAsync(
    jobName: "heartbeat-every-minute",
    enabled: false,
    cancellationToken);

var updatedCron = await scheduleAdmin.UpdateScheduledJobCronAsync(
    jobName: "heartbeat-every-minute",
    cronExpression: "*/5 * * * *",
    timeZone: "UTC",
    cancellationToken);

var runNowQueued = await scheduleAdmin.RunScheduledJobNowAsync(
    jobName: "heartbeat-every-minute",
    cancellationToken);
```

## Operational behavior

- Disabled schedules set `nextRunAtUtc` to null until re-enabled.
- Enabling recomputes `nextRunAtUtc` from current time.
- `RunScheduledJobNowAsync` enqueues an ad-hoc run and does not mutate cron schedule.

## Typical integration pattern

Most teams wrap this service in their own application command handlers or admin APIs.

```csharp
public sealed class ScheduleCommands
{
    private readonly IDurableScheduleAdminService _scheduleAdmin;

    public ScheduleCommands(IDurableScheduleAdminService scheduleAdmin)
    {
        _scheduleAdmin = scheduleAdmin;
    }

    public Task<bool> DisableAsync(string jobName, CancellationToken ct)
        => _scheduleAdmin.SetScheduledJobEnabledAsync(jobName, enabled: false, ct);
}
```
