go 23 lines · 1 tab

Robfig cron jobs with context cancellation and jitter

Leah Thompson Jan 2026
1 tab
package jobs

import (
  "context"
  "math/rand"
  "time"

  "github.com/robfig/cron/v3"
)

func Start(ctx context.Context, spec string, timeout time.Duration, fn func(context.Context) error) *cron.Cron {
  c := cron.New()
  c.AddFunc(spec, func() {
    jitter := time.Duration(rand.Int63n(int64(2 * time.Second)))
    time.Sleep(jitter)

    runCtx, cancel := context.WithTimeout(ctx, timeout)
    defer cancel()
    _ = fn(runCtx)
  })
  c.Start()
  return c
}
1 file · go Explain with highlit

Scheduled jobs get risky when deploys overlap or when jobs take longer than their interval. I use robfig/cron with a wrapper that creates a per-run context.WithTimeout, adds a bit of jitter to avoid synchronized load across instances, and logs start/finish. The jitter matters more than people think: without it, many pods run a cron at exactly the same second, which can spike a dependency. I also prefer idempotent jobs and, when needed, a distributed lock so only one instance does the work. The code below focuses on the core: wire the cron, add a wrapper that respects cancellation, and keep run durations bounded. In production you can add metrics (success/fail/duration) and alerts on repeated failures.


Related snips

Share this code

Here's the card — post it anywhere.

Robfig cron jobs with context cancellation and jitter — share card
Link copied