Home › Jenkins Cron

Jenkins Cron: Pipeline Triggers and Scheduling

How to schedule cron jobs in Jenkins using pipeline triggers. Covers the triggers { cron() } syntax, the Jenkins-specific H hash operator, timezone configuration, parameterized builds and debugging when a Jenkins cron trigger is not working.

Jenkins Pipeline Cron Trigger Syntax

In a Declarative Pipeline, scheduled builds are defined in the triggers block using cron(). Jenkins uses standard 5-field cron syntax plus the H operator - see the official Jenkins Pipeline Syntax docs.

pipeline {
    agent any
    triggers {
        cron('H 2 * * *')   // Daily around 2 AM (H spreads load)
    }
    stages {
        stage('Build') {
            steps {
                echo 'Running scheduled build'
            }
        }
    }
}

Declarative Pipeline (Jenkinsfile)

pipeline {
    agent any
    triggers {
        cron('0 9 * * 1-5')
    }
    stages { ... }
}

Freestyle job (Build periodically)

In a Freestyle job, go to Configure › Build Triggers › Build periodically and enter the cron expression directly - no triggers {} wrapper needed:

H 2 * * *

The Jenkins H Operator

H is the most important Jenkins-specific extension to standard cron syntax. It stands for "hash" - Jenkins replaces it with a value derived from the job name, so each job gets a consistent but different time. This prevents dozens of jobs all firing at the same second (e.g. midnight) and overloading the Jenkins controller.

H vs 0 - the key difference

Without H - all jobs fire at exactly midnight:

0 0 * * *   # Every job starts at 00:00:00
                                # Large spike, Jenkins slows down

With H - jobs spread across midnight hour:

H H * * *   # Job A: 00:14
             # Job B: 00:37
             # Job C: 00:52

H is deterministic, not random. The value is a hash of the job name, so it stays the same for that job every time. You can rely on it for scheduling, you just cannot control the exact minute.

ExpressionMeaningH equivalent of
H * * * *Every hour at a stable hash-determined minute0 * * * *
H/15 * * * *Every 15 minutes, starting at a hash offset*/15 * * * *
H/30 * * * *Every 30 minutes, hash-offset start*/30 * * * *
H 2 * * *Daily sometime in the 2 AM hour0 2 * * *
H H * * *Daily at a hash-determined hour and minute0 0 * * *
H H * * 1-5Weekdays at a hash-determined time0 2 * * 1-5
H(0-30) * * * *Random minute in the first half of each hour-
H H(3-4) * * *Daily sometime between 3 AM and 4 AM0 3 * * *

Jenkins Cron Examples

ExpressionDescription
H/5 * * * *Every 5 minutes (hash-offset)
H/15 * * * *Every 15 minutes
H/30 * * * *Every 30 minutes
H * * * *Every hour
H H/4 * * *Every 4 hours
H H/6 * * *Every 6 hours
H 2 * * *Daily around 2 AM
H 9 * * 1-5Weekdays around 9 AM
H 0 * * 0Every Sunday around midnight
H H 1 * *First day of every month
H 0 * * 1-5Every weekday around midnight
H 12 * * 1-5Weekdays at noon

Multiple Cron Triggers in One Pipeline

Use a multi-line string to define multiple schedules for the same pipeline:

pipeline {
    agent any
    triggers {
        cron('''
            H 0 * * 1-5    # Nightly on weekdays
            H 12 * * 1-5   # Midday on weekdays
            H H * * 0      # Weekly on Sunday
        ''')
    }
    stages { ... }
}

Jenkins Cron Timezone

By default, Jenkins uses the timezone of the Jenkins controller JVM. To specify a different timezone, prepend TZ=Zone/City on its own line before the cron expression:

triggers {
    cron('TZ=Europe/Madrid\nH 9 * * 1-5')
}

Or in a Freestyle job's "Build periodically" field:

TZ=America/New_York
H 9 * * 1-5

Parameterized Cron in Jenkins

To run a Jenkins job on a schedule with different parameters for each run, use the Parameterized Scheduler plugin. Parameters are passed after the cron expression using % as a separator:

// In the parameterized-scheduler field:
H 2 * * *   % ENV=production
H 4 * * *   % ENV=staging

// Multiple parameters:
H 2 * * *   % ENV=production;REGION=eu-west

For multi-branch pipelines, restrict the schedule to a specific branch to avoid building feature branches on cron:

pipeline {
    agent any
    triggers {
        cron(BRANCH_NAME == 'main' ? 'H 2 * * *' : '')
    }
    stages { ... }
}

Jenkins Cron Not Working - Checklist

Run the pipeline at least once manually

Jenkins does not activate the triggers block until the pipeline has run at least once. If you added a cron trigger to a new pipeline, run it manually first - only after the first run will Jenkins register the schedule. This is the most common cause of a Jenkins cron trigger silently doing nothing.

Check "Build periodically" is enabled

For Freestyle jobs, go to Configure › Build Triggers and confirm "Build periodically" is checked. For Pipeline jobs, the triggers { cron() } block in the Jenkinsfile activates it automatically after the first run.

Validate the cron expression

Jenkins shows a preview of when the expression will fire next, directly in the "Build periodically" field. If the preview shows an error or no upcoming time, the expression is wrong. Standard cron validators work too - Jenkins syntax is compatible except for the H operator.

Validate Expression

Check the Jenkins controller timezone

Jenkins uses the controller's JVM timezone, which may not be what you expect. Check it in Manage Jenkins › System Information - look for user.timezone. If the timezone is wrong, set TZ=Your/Timezone in the cron expression or configure -Duser.timezone in the JVM options.

Pipeline cron trigger not working after Jenkinsfile change

If you changed the triggers { cron() } expression in your Jenkinsfile, Jenkins does not pick up the change until the next run. Trigger one manual run after the change to register the new schedule.

H is not a valid expression outside Jenkins

The H operator is Jenkins-specific. It will not work in Linux crontab, GitHub Actions, Kubernetes or any other platform. If you copy a Jenkins expression to another tool and replace H with a number, use our cron validator to check the result.

Build and validate your Jenkins cron expression

Jenkins uses standard 5-field cron syntax. Generate the base expression here, then add the H operator if needed.