Skip to main content

Best Practices

Always Define a Static DefinitionId​

By default, JobMaster uses the handler class's full name as the job identity. If you rename the class or move it to a different namespace, the cluster will fail to map existing persisted jobs to the new code.

[JobMasterDefinitionId("HelloJob")]
public sealed class HelloJobHandler : IJobMasterHandler

Design for Idempotency​

In a distributed system, network flickers or node failures may cause a job to be retried even if it partially succeeded. Ensure your HandleAsync logic is safe to run multiple times — check whether the work was already done before performing it.

Keep Payloads Lean​

Message data is limited to 128 KB by default. Avoid passing large objects, byte arrays, or serialized blobs in the job payload.

  • Avoid: Passing a large JSON string or file content directly in MsgData.
  • Prefer: Uploading the data to storage (S3, database) and passing only the identifier in MsgData. Fetch the full data inside the handler.

Use Worker Lanes to Isolate Workloads​

Without lanes, all jobs compete for the same workers. A batch of long-running jobs can keep short, time-sensitive jobs waiting.

Assign lanes to isolate workloads by execution profile:

[JobMasterWorkerLane("HeavyCompute")]
public sealed class ReportGenerationHandler : IJobMasterHandler { ... }

[JobMasterWorkerLane("Transactional")]
public sealed class SendEmailHandler : IJobMasterHandler { ... }

Each lane requires dedicated workers configured to process it — see Workers & Lanes.

Avoid Sub-minute Recurring Schedules​

Sub-minute recurring schedules are supported, but expect 10–20 second start delays and potential execution overlaps in a distributed cluster. For tasks that require precise second-level execution, a .NET IHostedService or dedicated background loop is a better fit.