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 : IJobHandler

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 : IJobHandler { ... }

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

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.