Skip to content

High Availability

gocron supports multi-instance deployment with automatic leader election. Only the leader node runs the scheduler; followers stay on hot standby and take over within seconds if the leader goes down.

How It Works

gocron uses database row locking (SELECT ... FOR UPDATE) for leader election, inspired by the proven approach used in XXL-JOB.

  • A scheduler_lock table is created automatically on first startup
  • One instance acquires the lock and becomes the Leader, running all scheduled tasks
  • Other instances are Followers — they serve the Web UI and API but do not execute tasks
  • The Leader renews its lease every 5 seconds (lease expires after 15 seconds)
  • If the Leader shuts down gracefully, the lock is released immediately — failover is instant
  • If the Leader crashes, the lease expires and a Follower takes over within 15 seconds

Database Requirement

HA mode requires MySQL or PostgreSQL. SQLite does not support concurrent multi-process access, so leader election is automatically skipped in SQLite mode (single-node).

Setup

1. Install the First Node

Start the first node and complete the web installation wizard. Choose MySQL or PostgreSQL as the database engine.

bash
./gocron web --port 5920
# Open http://localhost:5920 and complete installation

2. Copy Configuration to Other Nodes

Copy the .gocron/conf/ directory from the first node to each additional node:

bash
scp -r .gocron/conf/ user@node2:/path/to/gocron/.gocron/conf/

The directory contains:

  • app.ini — database and application settings
  • install.lock — marks the installation as complete
  • .version — current application version

3. Start All Nodes

bash
# Node 1
./gocron web --port 5920

# Node 2
./gocron web --port 5921

Both nodes connect to the same database. One will become the Leader automatically.

Verify

Check the logs:

# Leader node
This node elected as leader: node1:12345
Starting to load scheduled tasks (this node is leader)

# Follower node
Scheduler infrastructure initialized
# (no "elected as leader" message)

Failover

Graceful Shutdown (Ctrl+C / SIGTERM)

Releasing leader lock: node1:12345
Stopping scheduler (this node lost leadership)

The Follower takes over within 1 second.

Crash / Kill -9

The lease expires after 15 seconds. A Follower detects the expired lock and takes over automatically.

Kubernetes Deployment

Use the official Helm Chart for Kubernetes. It enables managed mode, injects a shared authentication Secret into every Pod, coordinates schema bootstrap with a database advisory lock, and exposes all Ready replicas through one Service. No shared PVC or configuration copying is required.

bash
helm install gocron gocron/gocron \
  --set db.engine=postgres \
  --set db.host=postgresql.database.svc \
  --set db.port=5432 \
  --set db.user=gocron \
  --set db.password=replace-me \
  --set db.database=gocron \
  --set managed.authSecret=replace-with-at-least-32-random-characters \
  --set managed.encryptionKey=replace-with-another-32-random-characters \
  --set managed.admin.password=replace-with-a-strong-admin-password

See Kubernetes Deployment for existing Secret, scaling, HPA, Ingress, and administrator bootstrap configuration.

Architecture

┌─────────────┐     ┌─────────────┐
│   Node 1    │     │   Node 2    │
│  (Leader)   │     │ (Follower)  │
│             │     │             │
│ ┌─────────┐ │     │ ┌─────────┐ │
│ │Scheduler│ │     │ │  Standby│ │
│ │ (active)│ │     │ │  (idle) │ │
│ └─────────┘ │     │ └─────────┘ │
│ ┌─────────┐ │     │ ┌─────────┐ │
│ │ Web UI  │ │     │ │ Web UI  │ │
│ │  & API  │ │     │ │  & API  │ │
│ └─────────┘ │     │ └─────────┘ │
└──────┬──────┘     └──────┬──────┘
       │                   │
       └───────┬───────────┘

        ┌──────┴──────┐
        │  MySQL / PG │
        │             │
        │ scheduler   │
        │ _lock table │
        └─────────────┘