DEV Community

Shrijith Venkatramana
Shrijith Venkatramana

Posted on

Golang: Implementing Cron-Like Tasks / Executing Tasks at a Specific Time

Scheduling tasks in Golang is a common requirement for automation, background jobs, and periodic tasks. This article explores different approaches, from simple time-based execution to robust scheduling libraries and cloud-native solutions.

Am I A Joke To You?

1. Raw Implementation Using time Package

For simple task scheduling, you can use the time package in Go.

1.1 Using time.AfterFunc (One-time Delayed Execution)

package main

import (
    "fmt"
    "time"
)

func main() {
    time.AfterFunc(3*time.Second, func() {
        fmt.Println("Executed after 3 seconds")
    })

    // Prevent the program from exiting immediately
    time.Sleep(5 * time.Second)
}
Enter fullscreen mode Exit fullscreen mode

Output:

Executed after 3 seconds
Enter fullscreen mode Exit fullscreen mode

1.2 Using time.Ticker (Periodic Execution)

package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(2 * time.Second)
    defer ticker.Stop()

    for i := 0; i < 3; i++ {
        <-ticker.C
        fmt.Println("Task executed at:", time.Now())
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

Task executed at: 2025-02-07 12:00:00 +0000 UTC
Task executed at: 2025-02-07 12:00:02 +0000 UTC
Task executed at: 2025-02-07 12:00:04 +0000 UTC
Enter fullscreen mode Exit fullscreen mode

Pros:

  • Lightweight, built into Go
  • No external dependencies

Cons:

  • Requires manual handling of concurrency and persistence
  • Limited to running inside the same process

2. Using cron-like Libraries in Go

For more complex scheduling needs, use existing cron libraries that offer better flexibility and reliability.

2.1 Using robfig/cron (Crontab Syntax Support)

Install the library:

go get github.com/robfig/cron/v3
Enter fullscreen mode Exit fullscreen mode

Example:

package main

import (
    "fmt"
    "time"

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

func main() {
    c := cron.New()

    // Schedule a job every 5 seconds
    c.AddFunc("*/5 * * * * *", func() {
        fmt.Println("Cron job executed at:", time.Now())
    })

    c.Start()

    // Keep the main function running
    select {}
}
Enter fullscreen mode Exit fullscreen mode

2.2 Using gocron (Simpler API for Recurring Jobs)

Install:

go get github.com/go-co-op/gocron
Enter fullscreen mode Exit fullscreen mode

Example:

package main

import (
    "fmt"
    "time"

    "github.com/go-co-op/gocron"
)

func main() {
    s := gocron.NewScheduler(time.UTC)

    s.Every(10).Seconds().Do(func() {
        fmt.Println("Scheduled task executed at:", time.Now())
    })

    s.StartAsync()

    // Prevent exit
    select {}
}
Enter fullscreen mode Exit fullscreen mode

Pros:

  • More robust than time.Ticker
  • Supports standard cron expressions

Cons:

  • Runs within the Go process (needs process monitoring)

3. Using System cron (Best for CLI Execution)

Instead of running a Go process indefinitely, you can execute a Go script using Linux's cron daemon.

Example crontab Entry (Runs Every Minute)

* * * * * /path/to/your-go-program
Enter fullscreen mode Exit fullscreen mode

To set this up:

  1. Build the Go program:
   go build -o mytask mytask.go
Enter fullscreen mode Exit fullscreen mode
  1. Add it to crontab -e:
   * * * * * /path/to/mytask
Enter fullscreen mode Exit fullscreen mode

Pros:

  • More stable, managed by the OS
  • Easy to monitor and log

Cons:

  • Requires additional setup
  • Limited to CLI tasks

4. Cloud-Native Approaches

If you're deploying to the cloud, managed solutions may be better.

4.1 Google Cloud Run Jobs

  • Deploy a container that runs on a schedule.
  • Use Google Cloud Scheduler to trigger the job.
gcloud scheduler jobs create http my-job \
  --schedule="*/10 * * * *" \
  --uri="https://your-cloud-run-service-url"
Enter fullscreen mode Exit fullscreen mode

4.2 AWS Lambda with EventBridge

Create an AWS Lambda function and trigger it using EventBridge (formerly CloudWatch Events).

Example EventBridge rule (runs every 5 minutes):

{
  "ScheduleExpression": "rate(5 minutes)"
}
Enter fullscreen mode Exit fullscreen mode

4.3 Kubernetes CronJobs

Example cronjob.yaml (Runs Every Hour):

apiVersion: batch/v1
kind: CronJob
metadata:
  name: my-cronjob
spec:
  schedule: "0 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: my-job
            image: my-go-image
          restartPolicy: OnFailure
Enter fullscreen mode Exit fullscreen mode

Pros:

  • Fully managed, scalable
  • Works well in containerized environments

Cons:

  • Requires cloud setup and configuration

5. Comparing the Options: What Should You Use?

Approach Best For Pros Cons
time.Ticker Simple recurring jobs No dependencies, lightweight Needs manual persistence & recovery
robfig/cron Flexible job scheduling Crontab syntax, well-tested Runs inside app, process-dependent
System cron CLI-based scheduled tasks OS-managed, stable Limited logging, debugging overhead
Cloud Run Jobs Serverless scheduled tasks Fully managed, scalable Cloud-dependent, cold starts
Kubernetes CronJobs Containerized jobs Scalable, cloud-native Requires Kubernetes setup

Conclusion

  • If you need simple, in-process scheduling, use time.Ticker.
  • If you want crontab-like flexibility, use robfig/cron.
  • If your task is system-wide, use system cron.
  • For cloud-native workloads, use Cloud Run, Lambda, or Kubernetes CronJobs.

By choosing the right approach, you can ensure that your scheduled tasks run efficiently and reliably.

Top comments (0)