Deploy Terraform changes automatically on a schedule — whether that's a one-off maintenance window or a nightly recurring apply.
Scenario
Your team applies Terraform changes to production during a nightly maintenance window (2–4 AM UTC) to avoid business hours impact. You also want to automatically sync a dev environment every morning so developers start with a clean, known-good state.
✓Cloud integration connected with deploy permissions
✓Code pushed to GitHub (recommended for recurring applies — ensures the latest code is always used)
Part 1: Schedule a One-off Deployment (Maintenance Window)
Use a one-off scheduled deployment when you want to queue a specific deployment for a future date and time — for example, a production release during an approved maintenance window.
1Open your IaC project
2Click Deploy
3Under Timing, select Scheduled
4Set the date and time — all times are UTC
5Confirm the deployment — ops0 queues it and shows status: Scheduled with the fire time
What happens at the scheduled time
1Plan runs automatically — ops0 fetches the latest code and runs Terraform plan
2If plan passes policy checks → proceeds to apply (or waits for approval if required)
3If plan fails → apply is skipped, an incident is created, and your team is notified
4Apply runs and completes — notification sent to configured alert channels
Cancel before the fire time
You can cancel a queued scheduled deployment at any point before it fires. Click the deployment card → Cancel. After the scheduled time passes, the deployment cannot be cancelled.
Part 2: Set Up a Recurring Deployment
Use a recurring deployment when you want the same deployment to run automatically on a repeating schedule — for example, a nightly dev environment refresh.
1Open your IaC project
2Click Deploy
3Under Timing, select Recurring
4Enter a cron expression or choose a preset from the dropdown
5Click Save — the project card shows a Recurring badge with next run time
Cron expression presets
Preset
Expression
When
Every weekday morning
0 6 * * 1-5
Mon–Fri at 6:00 AM UTC
Nightly
0 2 * * *
Every day at 2:00 AM UTC
Weekly (Sunday)
0 0 * * 0
Sunday midnight UTC
Every 6 hours
0 */6 * * *
00:00, 06:00, 12:00, 18:00 UTC
First of month
0 0 1 * *
1st of each month at midnight UTC
Cron times are always UTC
ops0 evaluates all cron expressions in UTC. Convert your local maintenance window time to UTC before saving the schedule.
Part 3: Combine with Approval Gates
If your project has approval required enabled, scheduled deployments integrate with the approval flow automatically.
Step
What happens
Plan
Runs at the scheduled time as usual
Apply
Waits for approval — does not auto-apply
Approval window
Approver has until the next scheduled run to approve
Expiry
If the window closes without approval, the deployment expires and the next run creates a fresh plan
For recurring applies that should run fully automated with no human gate, you have two options:
Disable the approval requirement on the project under Settings → Approvals
Use a service account API key to auto-approve via the ops0 API, and trigger it from a CI/CD pipeline
Part 4: Managing Scheduled Deployments
View and monitor
1View all scheduled and recurring deployments: IaC → Deployments → filter by Scheduled
2Cancel a queued deployment: click the deployment → Cancel
3Disable a recurring schedule: project Settings → Scheduling → toggle off
4View run history: each recurring run creates a separate deployment record in the Deployments tab
Real-world example — Dev environment nightly reset
Project: dev-environment
Schedule: 0 6 * * 1-5 (weekdays 6 AM UTC)
Approval: Disabled
Branch: main
Result: Dev environment is refreshed each morning with the latest Terraform
code from the main branch. Developers arrive to a clean, known-good
state without manual intervention.
Verification
✓After saving, the project card shows the next run time
✓After the first run, the Deployments tab shows the run with a timestamp and status
✓Notification sent to configured alert channels on completion
Troubleshooting
Scheduled deployment didn't run
Check that the cloud integration credentials haven't expired. Scheduled runs use the same integration as manual deployments — if the IAM role session or service account key has rotated, update it under Integrations before the next run.
Recurring deployment keeps failing plan
The code may have a dependency that returns different values between runs (e.g. a data source fetching a dynamic value). Check the plan output for the specific error. Consider pinning the data source or switching to a static variable.
Can't find scheduled deployments in history
Filter the Deployments list by date range — scheduled runs appear as normal deployments with a Scheduled badge. If you recently enabled the schedule, no history exists until the first run fires.