CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/golang-github-com-go-co-op-gocron-v2

A Golang job scheduling library that lets you run Go functions at pre-determined intervals using cron expressions, fixed durations, daily, weekly, monthly, or one-time schedules with support for distributed deployments.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

gocron v2

A Go job scheduling library that runs functions at pre-determined intervals using cron expressions, fixed durations, daily/weekly/monthly schedules, or one-time execution. Includes distributed deployment support.

Package: github.com/go-co-op/gocron/v2 Install: go get github.com/go-co-op/gocron/v2@v2.19.1 Min Go: 1.21.4 Import: import "github.com/go-co-op/gocron/v2"

Quick Start

s, err := gocron.NewScheduler()
if err != nil {
    panic(err)
}
defer s.Shutdown()

// Add job
j, err := s.NewJob(
    gocron.DurationJob(5*time.Second),
    gocron.NewTask(func() {
        fmt.Println("running")
    }),
)

s.Start()
select {} // block

Common Patterns

// Fixed interval
gocron.DurationJob(5 * time.Minute)

// Cron expression
gocron.CronJob("*/5 * * * *", false)

// Daily at specific times
gocron.DailyJob(1, gocron.NewAtTimes(gocron.NewAtTime(9, 0, 0)))

// Task with parameters
gocron.NewTask(func(msg string, n int) {
    fmt.Println(msg, n)
}, "hello", 42)

// Job options
s.NewJob(
    gocron.DurationJob(time.Minute),
    gocron.NewTask(myFunc),
    gocron.WithName("my-job"),
    gocron.WithTags("worker", "cleanup"),
    gocron.WithSingletonMode(gocron.LimitModeReschedule),
)

Decision Guides

I need to schedule a job...

...every N seconds/minutes/hoursDurationJob for fixed intervals → DurationRandomJob for jittered intervals

...at specific times (9 AM, every Monday, etc.)CronJob for cron expressions → DailyJob for daily schedules → WeeklyJob for weekly schedules → MonthlyJob for monthly schedules

...just onceOneTimeJob

I need to prevent concurrent executions

Singleton Mode Guide — Prevent job from running with itself → Scheduler Limits Guide — Limit total concurrent jobs

I need to deploy across multiple instances

Leader Election Guide — Simple, all-or-nothing → Distributed Locking Guide — Per-job locking

I need observability

Logging Guide — Internal logging → Metrics Guide — Prometheus, StatsD integration → Lifecycle Monitoring Guide — Detailed events

Core Concepts

Scheduler

The main orchestrator. Create with NewScheduler, add jobs, call Start(), clean up with Shutdown().

Quick reference: Creating Schedulers | Managing Jobs | Lifecycle

Job Definition

Defines when a job runs: duration-based, cron-based, time-based, or one-time.

Quick reference: Duration Jobs | Cron Jobs | Time-Based Jobs | One-Time Jobs

Task

Defines what to run. Wrap any function with NewTask:

task := gocron.NewTask(func(ctx context.Context, msg string) {
    fmt.Println(msg)
}, "hello")

Context is auto-injected if first parameter is context.Context.

Quick reference: Tasks API

Job Options

Configure how a job runs: identity, concurrency, lifecycle, events, distributed settings.

Quick reference: Identity Options | Concurrency Options | Timing Options | Event Options | Distributed Options

Essential Patterns

Prevent Overlapping Runs

j, _ := s.NewJob(
    gocron.DurationJob(30*time.Second),
    gocron.NewTask(func() {
        time.Sleep(time.Minute) // takes longer than interval
    }),
    gocron.WithSingletonMode(gocron.LimitModeReschedule),
)

Learn more: Singleton Mode Guide

Graceful Shutdown

s, _ := gocron.NewScheduler(
    gocron.WithStopTimeout(30*time.Second),
)
defer s.Shutdown()

ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()

go func() {
    <-ctx.Done()
    if err := s.Shutdown(); err != nil {
        log.Printf("Shutdown error: %v", err)
    }
}()

s.Start()
select {} // block until shutdown

Learn more: Graceful Shutdown Guide

Distributed Deployment

// Leader election (simple)
s, _ := gocron.NewScheduler(
    gocron.WithDistributedElector(myElector),
)

// OR distributed locking (per-job)
s, _ := gocron.NewScheduler(
    gocron.WithDistributedLocker(myLocker),
)

Learn more: Leader Election | Distributed Locking

Event Handling

j, _ := s.NewJob(
    gocron.DurationJob(time.Minute),
    gocron.NewTask(myFunc),
    gocron.WithEventListeners(
        gocron.BeforeJobRuns(func(jobID uuid.UUID, jobName string) {
            log.Printf("Starting %s", jobName)
        }),
        gocron.AfterJobRunsWithError(func(jobID uuid.UUID, jobName string, err error) {
            log.Printf("Failed %s: %v", jobName, err)
        }),
    ),
)

Learn more: Event Options

Timezone-Aware Scheduling

// Scheduler timezone
loc, _ := time.LoadLocation("America/Chicago")
s, _ := gocron.NewScheduler(gocron.WithLocation(loc))

// Per-job timezone (cron only)
j, _ := s.NewJob(
    gocron.CronJob("TZ=America/New_York 0 9 * * *", false),
    gocron.NewTask(doWork),
)

Learn more: Time-Based Scheduling Guide

Error Handling

All errors are sentinel values; use errors.Is:

j, err := s.NewJob(
    gocron.CronJob("invalid", false),
    gocron.NewTask(myFunc),
)
if err != nil {
    if errors.Is(err, gocron.ErrCronJobParse) {
        // handle invalid cron
    }
    return err
}

Complete reference: Errors

Documentation Organization

Quick References

API Documentation

Complete API reference organized by category:

Guides

Task-oriented guides for common scenarios:

Getting Started

Jobs

Concurrency

Distributed

Observability

Advanced

Examples

Practical code examples organized by use case:

By Task

By Feature

By Scenario

Next Steps

docs

index.md

tile.json