RepoPilotOpen in app →

go-co-op/gocron

Easy and fluent Go cron scheduling. This is a fork from https://github.com/jasonlvhit/gocron

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 2w ago
  • 22+ active contributors
  • Distributed ownership (top contributor 38% of recent commits)
Show all 6 evidence items →
  • MIT licensed
  • CI configured
  • No test directory detected

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/go-co-op/gocron)](https://repopilot.app/r/go-co-op/gocron)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/go-co-op/gocron on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: go-co-op/gocron

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/go-co-op/gocron shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 2w ago
  • 22+ active contributors
  • Distributed ownership (top contributor 38% of recent commits)
  • MIT licensed
  • CI configured
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live go-co-op/gocron repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/go-co-op/gocron.

What it runs against: a local clone of go-co-op/gocron — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in go-co-op/gocron | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch v2 exists | Catches branch renames | | 4 | Last commit ≤ 46 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>go-co-op/gocron</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of go-co-op/gocron. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/go-co-op/gocron.git
#   cd gocron
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of go-co-op/gocron and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "go-co-op/gocron(\\.git)?\\b" \\
  && ok "origin remote is go-co-op/gocron" \\
  || miss "origin remote is not go-co-op/gocron (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify v2 >/dev/null 2>&1 \\
  && ok "default branch v2 exists" \\
  || miss "default branch v2 no longer exists"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 46 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~16d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/go-co-op/gocron"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

gocron is a Go job scheduling library that executes functions at predetermined intervals (fixed duration, cron expressions, specific times, or random delays). It provides a fluent API to define, manage, and monitor scheduled jobs with features like job deduplication, concurrency limits, and distributed scheduling support across multiple nodes. Modular design: scheduler.go is the orchestrator managing job lifecycle; job.go encapsulates individual task definitions; executor.go handles parallel execution with rate limiting; distributed.go adds multi-node coordination; monitor.go provides observability hooks. Examples/ directory contains runnable demo patterns, and mocks/ provides testable interfaces for integration testing.

👥Who it's for

Go backend engineers building services that need reliable task scheduling (batch processing, data sync, periodic health checks, report generation). Platform teams maintaining shared scheduling infrastructure, and organizations using the companion gocron-ui dashboard for job visibility and manual triggering.

🌱Maturity & risk

Production-ready. The project is actively maintained with v2 being the current major version (v1 is deprecated as per migration_v1_to_v2.md), has comprehensive CI/CD via GitHub Actions (go_test.yml, codeql-analysis.yml), extensive test coverage (scheduler_test.go, job_test.go, logger_test.go), and follows Go best practices with golangci linting and pre-commit hooks. Regular dependency updates via dependabot.yml indicate active stewardship.

Low risk for core functionality. Dependencies are minimal and stable (google/uuid, robfig/cron/v3 for CRON parsing, jonboulle/clockwork for testing time). The main risk is feature complexity: distributed.go suggests eventual-consistency patterns for multi-node scheduling that require careful implementation. No obvious single-maintainer risk given it's a go-co-op organization project.

Active areas of work

Active v2 development with focus on stability and monitoring. The presence of scheduler_monitor_test.go and scheduler_monitor.go indicates recent work on observability. Copilot instructions (.github/copilot-instructions.md) suggest ongoing documentation. gocron-monitor-test/ subdirectory with debug_restart.go indicates testing of scheduler resilience scenarios.

🚀Get running

git clone https://github.com/go-co-op/gocron.git
cd gocron
go mod download
make test  # (if Makefile defines test target)
go test ./...

Daily commands: This is a library, not a server. To test locally: go test ./.... To use in your code, follow the Quick Start pattern: create scheduler with gocron.NewScheduler(), add jobs with s.NewJob(), call s.Start(), and s.Shutdown() on graceful termination. See example_test.go for runnable patterns.

🗺️Map of the codebase

  • scheduler.go: Core orchestrator managing job registry, start/stop lifecycle, and scheduling loop—essential to understand the main event loop
  • job.go: Job interface and common job types (DurationJob, CronJob); defines what a schedulable task is and when it should run
  • executor.go: Handles actual function invocation, concurrency limits, singleton mode, and error propagation—critical for execution guarantees
  • distributed.go: Multi-node coordination abstractions; understand this before deploying to scaled systems with leader election
  • monitor.go: Observability hooks and metrics collection points—needed if integrating with monitoring/alerting systems
  • example_test.go: Comprehensive usage patterns showing all job types and API surfaces; best reference for getting started
  • errors.go: Library-specific error types; understand error semantics before building error handling in client code

🛠️How to make changes

For scheduling logic: modify job.go (next execution time calculation) and scheduler.go (job dispatch). For execution behavior: edit executor.go (concurrency, limits, error handling). For new job types (beyond Duration/Cron/Datetime): extend the Job interface. For monitoring/hooks: extend monitor.go. Always add tests to corresponding _test.go files and check golangci-lint compliance.

🪤Traps & gotchas

No required environment variables or external services. However: (1) Job functions that panic are recovered but logged—monitor logger output for silent failures. (2) By default, jobs run in FIFO order within their scheduled window; ensure executor.go concurrency limits match your throughput needs. (3) Timezone handling is locale-dependent in CronJob; always test cron expressions in the exact deployment timezone. (4) Shutdown is graceful but has timeout semantics—long-running jobs may be interrupted; design idempotent tasks. (5) No persistent job store—scheduler state is lost on process restart; for durability, use distributed.go with external coordination.

💡Concepts to learn

  • Job scheduling with cron expressions — gocron delegates cron parsing to robfig/cron; understanding cron syntax (minute, hour, day, month, dow fields) is essential for defining recurring schedules correctly
  • Graceful shutdown and job cancellation — scheduler.Shutdown() and ShutdownWithContext() implement context-aware teardown; critical for preventing orphaned goroutines and data loss in production
  • Goroutine pools and concurrency limits — executor.go manages concurrent job execution with configurable limits; misunderstanding these can lead to resource exhaustion or unintended serialization
  • Distributed consensus and leader election — distributed.go provides abstractions for multi-node coordination; understanding leader election (often via etcd/Consul) prevents duplicate job execution across instances
  • Clock mocking and time-based testing — Uses jonboulle/clockwork for deterministic time control in tests; essential for reliable unit tests of scheduled jobs without flakiness
  • Singleton pattern for job execution — executor.go supports singleton mode to prevent overlapping executions of the same job; critical for long-running tasks that must not pile up
  • Interface-based design for testability — mocks/ directory provides mock implementations of Scheduler, Job, Logger, and Distributed interfaces; enables isolated unit testing without full scheduler
  • robfig/cron — Upstream CRON expression parser (v3.0.1 in go.mod); gocron wraps this for human-friendly scheduling
  • go-co-op/gocron-ui — Official companion web dashboard for monitoring, triggering, and managing gocron jobs in real-time—mentioned in README
  • jasonlvhit/gocron — Original upstream project before the fork; go-co-op/gocron is the maintained fork with v2 improvements
  • etcd-io/etcd — Common choice for distributed coordination in multi-node gocron setups (leader election, job locking via distributed.go layer)
  • prometheus/client_golang — Standard instrumentation for exposing gocron metrics (job execution times, failures) to monitoring systems

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive integration tests for distributed scheduler modes

The repo has distributed.go and examples/elector/main.go indicating distributed scheduling support, but there are no dedicated integration tests in scheduler_test.go or a new distributed_test.go file. This is critical for a scheduling library as distributed coordination bugs can cause missed jobs or duplicate executions. New contributors can add tests for leader election, job locking across instances, and failover scenarios.

  • [ ] Create distributed_test.go with tests for distributed.Locker interface implementations
  • [ ] Add integration tests verifying job execution is coordinated across multiple scheduler instances
  • [ ] Add test cases for leader election failures and recovery in examples/elector/main.go
  • [ ] Reference distributed.go implementation to test Lock/Unlock/IsLeader behaviors

Add missing unit tests for monitor.go and scheduler_monitor.go

The monitor.go file exists but there's only scheduler_monitor_test.go. The README mentions gocron-ui for real-time monitoring, indicating monitoring is a core feature. However, monitor.go lacks dedicated test coverage. This is important for ensuring monitoring doesn't introduce race conditions or memory leaks (note: goleak is already a dependency).

  • [ ] Create monitor_test.go covering all exported functions in monitor.go
  • [ ] Add tests for monitor state transitions and metrics collection
  • [ ] Add goroutine leak detection tests using go.uber.org/goleak (already in go.mod)
  • [ ] Test monitor behavior with scheduler start/stop cycles in gocron-monitor-test/

Add end-to-end tests using clockwork mocking for job execution timing

The repo depends on github.com/jonboulle/clockwork v0.5.0 (a time mocking library), but there are no visible end-to-end tests using it in scheduler_test.go. This allows testing complex scheduling scenarios (timezone handling, DST, cron expression edge cases) without sleeping. Given robfig/cron/v3 is a dependency, contributors can add tests for edge cases like leap seconds or month-end scheduling.

  • [ ] Create a new test file e2e_scheduler_test.go using clockwork.NewFakeClock()
  • [ ] Add tests for timezone-aware scheduling with DST transitions using time mocking
  • [ ] Add tests for cron expression edge cases (e.g., 'L' for last day of month, '?' wildcards) verified against robfig/cron/v3
  • [ ] Add tests for job retry logic and error handling with deterministic time progression

🌿Good first issues

  • Add missing test coverage for util.go functions (currently no util_test.go exists or is minimal)—inspect util.go for untested helper logic and write table-driven tests
  • Enhance logger_test.go with more output format scenarios—currently tests basic functionality but missing coverage for structured logging with fields and levels across different log levels
  • Document the distributed.go interfaces in code comments with real-world multi-node examples (e.g., etcd-based leader election scenario)—the interfaces exist but lack concrete implementation guidance in comments

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 8e553c0 — fix: remove jobs and respect stopTime in NextRuns when WithStopDateTime is set (#922) (jcheyer)
  • 54f6bd8 — test: enhancements to testing speed and reliablity (#920) (JohnRoesler)
  • 9b8a3f7 — Expose job schedule information via Schedule() method on Job interface (#919) (Copilot)
  • 2e69a26 — feat: add IsRunning() and LastRunCompletedAt() to Job interface (#918) (Copilot)
  • 1e25a3b — feat: add WithDSTPolicy option for DST spring-forward handling (#917) (Copilot)
  • 89567e9 — perf: replace string allocation with bytes.Compare in Jobs() UUID sort (#914) (huynhanx03)
  • a6875f0 — Fix CronJob duplicate execution during DST fall-back (#912) (Copilot)
  • c304de1 — feat: add ShutdownWithContext and StopJobsWithContext (#913) (huynhanx03)
  • 5b307f5 — docs: clarify NextRun/NextRuns require scheduler to be started (#910) (Copilot)
  • 102b2b2 — Change GitHub Sponsors username in FUNDING.yml (JohnRoesler)

🔒Security observations

The gocron project demonstrates generally strong security practices with minimal attack surface. As a pure Go scheduling library, it avoids common web vulnerabilities. The codebase has no apparent hardcoded secrets or suspicious dependencies. Primary concerns are the vulnerability disclosure process (which should not be public GitHub issues) and clear deprecation timelines for v1. The project would benefit from implementing a private security vulnerability reporting mechanism and ensuring regular dependency vulnerability scanning. Overall security posture is good for a scheduling library, with low risk for typical use cases.

  • Low · Vulnerability Reporting via Public Issue Tracker — SECURITY.md. The SECURITY.md file directs users to report vulnerabilities by opening a public GitHub issue. This is not a recommended security practice as it exposes vulnerability details publicly before patches are available, potentially allowing malicious actors to exploit the vulnerability. Fix: Implement a private security vulnerability disclosure process. Use GitHub Security Advisories or set up a dedicated security email (security@domain.com). Provide a responsible disclosure policy that allows 90 days for patching before public disclosure.
  • Low · Deprecated Version Not Patched — SECURITY.md. Version 1.x.x is marked as deprecated with no security patches. Users on v1 are at continued risk without clear guidance on migration timeline. Fix: Provide a clear deprecation timeline and end-of-life date for v1. Create migration documentation for v1 to v2. Consider implementing automatic security warnings for v1 users in package registries.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · go-co-op/gocron — RepoPilot