2023-11-14 16:26:44 +00:00
# gocron: A Golang Job Scheduling Package
2023-11-08 17:11:42 +00:00
[](https://github.com/go-co-op/gocron/actions)
 [](https://pkg.go.dev/github.com/go-co-op/gocron/v2)
gocron is a job scheduling package which lets you run Go functions at pre-determined intervals.
2025-10-08 16:24:51 +00:00
> Looking for a visual interface?
> Check out [**gocron-ui**](https://github.com/go-co-op/gocron-ui) — a lightweight web dashboard to monitor, trigger, and manage your `gocron` jobs in real time.
2023-11-08 17:11:42 +00:00
If you want to chat, you can find us on Slack at
[<img src="https://img.shields.io/badge/gophers-gocron-brightgreen?logo=slack"> ](https://gophers.slack.com/archives/CQ7T0T1FW )
## Quick Start
```
go get github.com/go-co-op/gocron/v2
```
```golang
package main
import (
"fmt"
"time"
"github.com/go-co-op/gocron/v2"
)
func main() {
// create a scheduler
s, err := gocron.NewScheduler()
if err != nil {
// handle error
}
// add a job to the scheduler
j, err := s.NewJob(
gocron.DurationJob(
10*time.Second,
),
gocron.NewTask(
func(a string, b int) {
// do things
2023-12-28 20:23:53 +00:00
},
2023-11-08 17:11:42 +00:00
"hello",
1,
),
)
if err != nil {
// handle error
}
// each job has a unique id
fmt.Println(j.ID())
// start the scheduler
s.Start()
2024-01-17 17:50:33 +00:00
// block until you are ready to shut down
select {
case < -time.After ( time . Minute ) :
}
2023-11-08 17:11:42 +00:00
// when you're done, shut it down
err = s.Shutdown()
if err != nil {
// handle error
}
}
```
2024-03-12 13:37:11 +00:00
## Examples
- [Go doc examples ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#pkg-examples )
- [Examples directory ](examples )
2025-10-22 19:38:24 +00:00
## Articles & Blog Posts
Community articles and tutorials about using gocron:
- [Building a dynamic, highly available scheduler in Go ](https://tech.efg.gg/posts/2025/highly-available-scheduler-in-go/ ) - A deep dive into building a highly available scheduler using gocron, MongoDB change streams, and leader election patterns for the FACEIT Watch platform.
2023-12-11 16:39:59 +00:00
## Concepts
- **Job**: The job encapsulates a "task", which is made up of a go function and any function parameters. The Job then
provides the scheduler with the time the job should next be scheduled to run.
- **Scheduler**: The scheduler keeps track of all the jobs and sends each job to the executor when
it is ready to be run.
- **Executor**: The executor calls the job's task and manages the complexities of different job
execution timing requirements (e.g. singletons that shouldn't overrun each other, limiting the max number of jobs running)
2023-11-08 17:11:42 +00:00
## Features
2023-12-13 16:48:53 +00:00
### Job types
Jobs can be run at various intervals.
- [**Duration** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#DurationJob ):
Jobs can be run at a fixed `time.Duration` .
- [**Random duration** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#DurationRandomJob ):
Jobs can be run at a random `time.Duration` between a min and max.
- [**Cron** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#CronJob ):
Jobs can be run using a crontab.
- [**Daily** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#DailyJob ):
Jobs can be run every x days at specific times.
- [**Weekly** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WeeklyJob ):
Jobs can be run every x weeks on specific days of the week and at specific times.
- [**Monthly** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#MonthlyJob ):
Jobs can be run every x months on specific days of the month and at specific times.
2023-12-19 03:13:37 +00:00
- [**One time** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#OneTimeJob ):
2024-06-23 18:14:35 +00:00
Jobs can be run at specific time(s) (either once or many times).
2023-12-13 16:48:53 +00:00
2025-10-22 03:09:46 +00:00
### Interval Timing
Jobs can be scheduled with different interval timing modes.
- [**Interval from scheduled time (default)** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#DurationJob ):
By default, jobs calculate their next run time from when they were scheduled to start, resulting in fixed intervals
regardless of execution time. Good for cron-like scheduling at predictable times.
- [**Interval from completion time** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithIntervalFromCompletion ):
Jobs can calculate their next run time from when they complete, ensuring consistent rest periods between executions.
Ideal for rate-limited APIs, resource-intensive jobs, and scenarios where execution time varies.
2023-12-13 16:48:53 +00:00
### Concurrency Limits
Jobs can be limited individually or across the entire scheduler.
- [**Per job limiting with singleton mode** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithSingletonMode ):
Jobs can be limited to a single concurrent execution that either reschedules (skips overlapping executions)
or queues (waits for the previous execution to finish).
- [**Per scheduler limiting with limit mode** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithLimitConcurrentJobs ):
Jobs can be limited to a certain number of concurrent executions across the entire scheduler
using either reschedule (skip when the limit is met) or queue (jobs are added to a queue to
wait for the limit to be available).
- **Note:** A scheduler limit and a job limit can both be enabled.
### Distributed instances of gocron
Multiple instances of gocron can be run.
- [**Elector** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithDistributedElector ):
An elector can be used to elect a single instance of gocron to run as the primary with the
other instances checking to see if a new leader needs to be elected.
2024-01-17 21:39:11 +00:00
- Implementations: [go-co-op electors ](https://github.com/go-co-op?q=-elector&type=all&language=&sort= )
(don't see what you need? request on slack to get a repo created to contribute it!)
2023-12-13 16:48:53 +00:00
- [**Locker** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithDistributedLocker ):
A locker can be used to lock each run of a job to a single instance of gocron.
2024-04-22 18:52:27 +00:00
Locker can be at job or scheduler, if it is defined both at job and scheduler then locker of job will take precedence.
2025-05-16 19:15:33 +00:00
- See Notes in the doc for [Locker ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#Locker ) for
details and limitations of the locker design.
2024-01-17 21:39:11 +00:00
- Implementations: [go-co-op lockers ](https://github.com/go-co-op?q=-lock&type=all&language=&sort= )
(don't see what you need? request on slack to get a repo created to contribute it!)
2023-12-13 16:48:53 +00:00
### Events
Job events can trigger actions.
- [**Listeners** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithEventListeners ):
Can be added to a job, with [event listeners ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#EventListener ),
or all jobs across the
[scheduler ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithGlobalJobOptions )
to listen for job events and trigger actions.
### Options
Many job and scheduler options are available.
- [**Job options** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#JobOption ):
Job options can be set when creating a job using `NewJob` .
- [**Global job options** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithGlobalJobOptions ):
Global job options can be set when creating a scheduler using `NewScheduler`
and the `WithGlobalJobOptions` option.
- [**Scheduler options** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#SchedulerOption ):
Scheduler options can be set when creating a scheduler using `NewScheduler` .
### Logging
Logs can be enabled.
- [Logger ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#Logger ):
The Logger interface can be implemented with your desired logging library.
The provided NewLogger uses the standard library's log package.
2024-01-17 21:39:11 +00:00
### Metrics
2025-12-02 16:25:51 +00:00
Metrics may be collected from the execution of each job and scheduler lifecycle events.
2024-01-17 21:39:11 +00:00
- [**Monitor** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#Monitor ):
A monitor can be used to collect metrics for each job from a scheduler.
2026-01-28 16:27:20 +00:00
- Implementations: There are currently no open source implementations of the Monitor interface available.
We'd love for you to be the first to contribute one! Check out the [Monitor interface documentation ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#Monitor )
to get started, or reach out on [Slack ](https://gophers.slack.com/archives/CQ7T0T1FW ) if you'd like to discuss your implementation.
- [**MonitorStatus** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#MonitorStatus ):
Extends Monitor with status and error tracking for each job.
- Implementations: There are currently no open source implementations of the MonitorStatus interface available.
We'd love for you to be the first to contribute one! Check out the [MonitorStatus interface documentation ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#MonitorStatus )
to get started, or reach out on [Slack ](https://gophers.slack.com/archives/CQ7T0T1FW ) if you'd like to discuss your implementation.
2025-12-02 16:25:51 +00:00
- [**SchedulerMonitor** ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#SchedulerMonitor ):
A scheduler monitor provides comprehensive observability into scheduler and job lifecycle events.
**Available Metrics:**
- **Scheduler Lifecycle**: `SchedulerStarted` , `SchedulerStopped` , `SchedulerShutdown`
- **Job Management**: `JobRegistered` , `JobUnregistered` - track jobs added/removed from scheduler
- **Job Execution**: `JobStarted` , `JobRunning` , `JobCompleted` , `JobFailed` - monitor job execution flow
- **Performance**: `JobExecutionTime` , `JobSchedulingDelay` - measure job duration and scheduling lag
- **Concurrency**: `ConcurrencyLimitReached` - detect when singleton or limit mode constraints are hit
**Derived Metrics** (calculable from events):
- Error rate: `JobFailed / (JobCompleted + JobFailed)`
- Average execution time: from `JobExecutionTime` events
- Active jobs: `JobRegistered - JobUnregistered`
- Current queue depth: `JobStarted - (JobCompleted + JobFailed)`
**Example - Prometheus Integration:**
```go
type PrometheusMonitor struct {
jobsCompleted prometheus.Counter
jobsFailed prometheus.Counter
executionTime prometheus.Histogram
schedulingDelay prometheus.Histogram
}
func (p *PrometheusMonitor) JobExecutionTime(job gocron.Job, duration time.Duration) {
p.executionTime.Observe(duration.Seconds())
}
func (p *PrometheusMonitor) JobSchedulingDelay(job gocron.Job, scheduled, actual time.Time) {
if delay := actual.Sub(scheduled); delay > 0 {
p.schedulingDelay.Observe(delay.Seconds())
}
}
// Initialize scheduler with monitor
s, _ := gocron.NewScheduler(gocron.WithSchedulerMonitor(monitor))
```
**Use Cases:** Prometheus metrics, custom dashboards, alerting systems, performance monitoring
2024-01-17 21:39:11 +00:00
2026-01-28 16:27:20 +00:00
- Implementations: There are currently no open source implementations of the SchedulerMonitor interface available.
We'd love for you to be the first to contribute one! Check out the [SchedulerMonitor interface documentation ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#SchedulerMonitor )
to get started, or reach out on [Slack ](https://gophers.slack.com/archives/CQ7T0T1FW ) if you'd like to discuss your implementation.
2023-12-13 16:48:53 +00:00
### Testing
The gocron library is set up to enable testing.
- Mocks are provided in [the mock package ](mocks ) using [gomock ](https://github.com/uber-go/mock ).
- Time can be mocked by passing in a [FakeClock ](https://pkg.go.dev/github.com/jonboulle/clockwork#FakeClock )
to [WithClock ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithClock ) -
see the [example on WithClock ](https://pkg.go.dev/github.com/go-co-op/gocron/v2#example-WithClock ).
2023-11-08 17:11:42 +00:00
## Supporters
2023-12-11 16:39:59 +00:00
We appreciate the support for free and open source software!
2023-12-12 20:46:14 +00:00
This project is supported by:
2025-04-03 17:27:12 +00:00
[JetBrains ](https://www.jetbrains.com/?from=gocron )
2024-12-06 20:06:44 +00:00
2025-04-03 17:27:12 +00:00
< a href = "https://www.jetbrains.com/?from=gocron" >
< picture >
< source media = "(prefers-color-scheme: dark)" srcset = "assets/jetbrains-mono-white.png" / >
< source media = "(prefers-color-scheme: light)" srcset = "https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.png" / >
< img alt = "JetBrains logo" src = "https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.png" / >
< / picture >
< / a >
2024-12-06 20:06:44 +00:00
[Sentry ](https://sentry.io/welcome/ )
2023-11-08 17:11:42 +00:00
2025-04-03 17:27:12 +00:00
< a href = "https://sentry.io/?utm_source=github&utm_medium=logo" >
< picture >
< source media = "(prefers-color-scheme: dark)" srcset = "assets/sentry-wordmark-light-280x84.png" / >
< source media = "(prefers-color-scheme: light)" srcset = "https://sentry-brand.storage.googleapis.com/sentry-wordmark-dark-280x84.png" / >
< img alt = "Sentry logo" src = "https://sentry-brand.storage.googleapis.com/sentry-wordmark-dark-280x84.png" / >
< / picture >
< / a >
2025-01-31 16:25:26 +00:00
2023-11-08 17:11:42 +00:00
## Star History
2025-04-03 17:27:12 +00:00
< a href = "https://www.star-history.com/#go-co-op/gocron&Date" >
< picture >
< source media = "(prefers-color-scheme: dark)" srcset = "https://api.star-history.com/svg?repos=go-co-op/gocron&type=Date&theme=dark" / >
< source media = "(prefers-color-scheme: light)" srcset = "https://api.star-history.com/svg?repos=go-co-op/gocron&type=Date" / >
< img alt = "Star History Chart" src = "https://api.star-history.com/svg?repos=go-co-op/gocron&type=Date" / >
< / picture >
< / a >