A GitLab pipeline schedule runs a pipeline on a cron expression against a branch or tag you choose. It runs with the permissions of the schedule's owner, so the owner matters. Stagger cron times and use inputs rather than variables to keep scheduled scan jobs predictable.
How a schedule is defined
You create a schedule in the project, pick a preset interval or enter a custom cron expression, and choose the target branch or tag. According to GitLab's pipeline schedule documentation, schedules cannot run more often than the instance's maximum scheduled pipeline frequency, and manual runs of a schedule are limited to once per minute.
| Setting | What to know |
|---|---|
| Cron | Preset or custom expression |
| Target | A branch or tag. Protected branches need merge permission. |
| Owner | The user who created it. Pipeline runs use their permissions. |
| Inputs and variables | Up to 20 inputs per schedule. Docs recommend inputs over variables. |
The owner problem
Because the pipeline uses the owner's permissions, access to protected environments and the job token follows that person. If the owner is blocked or removed, the schedule may become inactive until a Maintainer or Owner takes ownership.
That is a quiet failure. A scan job that stops when someone leaves is exactly the case to design against.
- Create schedules under a service account where your policy allows it.
- Keep a list of schedules and their human backup owner.
- After any offboarding, check for inactive schedules in each project.
Stagger the times
GitLab suggests spreading schedules out, for example at 5 and 15 minutes past the hour, rather than running many at the top of the hour. For a security team with many projects, that means picking a different minute per project. One approach is to derive the minute from a hash of the project name so it stays stable.
A practical setup
- Add a rule in your CI file so the scan job runs on the pipeline source for scheduled pipelines.
- Create one nightly schedule on the default branch.
- Create a weekly schedule on each release branch you still support.
- Pass the scan depth as an input, such as quick for nightly and full for weekly.
- Send the results to wherever your team triages findings.
nightly_scan:
stage: test
script: ./scripts/scan.sh
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
What to watch
A scheduled pipeline that fails still needs a human to notice. Pair it with a missing run alert, as in how to detect a silently failing scheduled scan. Check your instance limits too, because the docs say a project has a maximum number of schedules and you may need to delete unused ones.
Quick check
Whose permissions does a scheduled pipeline use?
The schedule owner's. A manual run uses the permissions of whoever triggered it.
What happens if the owner leaves?
The schedule may become inactive. A Maintainer or Owner can take ownership to reactivate it.
Sources
Last reviewed: 19 October 2026.