Scheduled Operations
Scheduled operations let you automate recurring tasks on your servers - deploy on a schedule, run maintenance scripts, restart containers, or reboot servers. Operations support cron expressions, pre-execution conditions, retry logic, and chaining multiple operations together.
Operation Types
Section titled “Operation Types”| Type | What it does | Requires |
|---|---|---|
| Deploy | Deploys an application to its server | Application |
| Command | Runs a shell command on a server | Server, command text |
| Restart | Restarts an application’s Docker container | Server, Application |
| Reboot | Reboots a server | Server |
Creating a Scheduled Operation
Section titled “Creating a Scheduled Operation”- Navigate to Scheduled Operations in the sidebar
- Click Create Operation
- Choose the operation type
- Configure the schedule (cron or one-time)
- Set targeting (which server/application)
- Optionally add conditions and post-actions
- Click Create
The operation starts in the Active state and will execute according to its schedule.
Schedule Types
Section titled “Schedule Types”Cron (recurring)
Section titled “Cron (recurring)”Standard 5-field cron expressions for recurring schedules. All times are evaluated in the timezone you specify (defaults to UTC).
# Field order: minute hour day-of-month month day-of-week
0 3 * * * # Every day at 3:00 AM*/15 * * * * # Every 15 minutes0 0 * * 0 # Every Sunday at midnight0 9 1 * * # First day of every month at 9:00 AM30 2 * * 1-5 # Weekdays at 2:30 AMOne-time
Section titled “One-time”Schedule a single execution at a specific date and time. The operation runs once and then stays in the system for history.
Operation Parameters
Section titled “Operation Parameters”Deploy
Section titled “Deploy”Deploy an application to its server. Optionally specify a git ref to deploy.
| Parameter | Description |
|---|---|
| Application | The application to deploy |
| Commit ref | Branch, tag, or SHA to deploy (defaults to the app’s deploy branch) |
Command
Section titled “Command”Run a shell command on a server. The command executes via the runner agent.
| Parameter | Description |
|---|---|
| Server | Target server |
| Command | Shell command to run (max 4,096 characters) |
Examples:
# Clean up old Docker imagesdocker image prune -af --filter "until=168h"
# Run a database backuppg_dump -U postgres mydb > /backups/mydb-$(date +%Y%m%d).sql
# Clear application cachecd /opt/app && docker compose exec -T api python manage.py clearcacheRestart
Section titled “Restart”Restart an application’s Docker container. Useful for picking up configuration changes or clearing memory.
| Parameter | Description |
|---|---|
| Server | Target server |
| Application | Application whose container to restart |
Reboot
Section titled “Reboot”Reboot a server. If the server has a cloud provider linked, the reboot uses the cloud API. Otherwise, it sends sudo reboot via the runner.
| Parameter | Description |
|---|---|
| Server | Target server |
Execution Behavior
Section titled “Execution Behavior”Timeout
Section titled “Timeout”Each run has a timeout (default: 10 minutes, configurable from 30 seconds to 1 hour). If a run exceeds the timeout, it’s marked as timed out.
Concurrency
Section titled “Concurrency”When a new trigger fires while a previous run is still executing:
| Policy | Behavior | Available for |
|---|---|---|
| Skip (default) | Skip the new trigger; let the current run finish | All types |
| Queue | Queue the new trigger; execute after the current run completes | All types |
| Replace | Cancel the current run and start the new one | Command only |
Retries
Section titled “Retries”Failed runs can be automatically retried:
- Max retries: 0-3 attempts (default: 0, no retries)
- Retry delay: 30-600 seconds between attempts (default: 60 seconds)
If an operation accumulates 5 consecutive failures, it’s automatically paused to prevent cascading issues. Resume it manually after fixing the underlying problem.
Conditions
Section titled “Conditions”Conditions are checked before each execution. If any condition fails, the run is skipped.
HTTP Check
Section titled “HTTP Check”Make an HTTP request and verify the response before executing.
| Parameter | Description |
|---|---|
| URL | Endpoint to check |
| Expected status | HTTP status code to require (e.g., 200) |
Use case: Only deploy if the staging health check is passing.
Command Check
Section titled “Command Check”Run a shell command on the target server and verify the output.
| Parameter | Description |
|---|---|
| Command | Shell command to execute |
| Expected output | String the output must contain |
Use case: Only run cleanup if disk usage is above a threshold.
Previous Run Check
Section titled “Previous Run Check”Verify that another operation’s last run had a specific status.
| Parameter | Description |
|---|---|
| Operation | The other scheduled operation to check |
| Required status | Status to require (e.g., succeeded) |
Use case: Only deploy production after staging deployment succeeded.
Post-Action Chaining
Section titled “Post-Action Chaining”Trigger other scheduled operations after a run completes. This lets you build multi-step workflows.
How it works
Section titled “How it works”- A parent operation completes (success or failure)
- Each post-action is evaluated against its trigger condition
- Matching post-actions create new runs for their target operations
- Target operations execute with an optional delay
Trigger conditions
Section titled “Trigger conditions”| Trigger | Fires when |
|---|---|
| On success | Parent run succeeded |
| On failure | Parent run failed |
| Always | Regardless of parent outcome |
Chain depth
Section titled “Chain depth”Operations can chain up to 5 levels deep. This prevents runaway chains.
Deploy staging (depth 0) -> Run tests (depth 1) -> Deploy production (depth 2) -> Health check (depth 3)Each post-action can have a delay of 0-300 seconds before the target operation executes. Use this to wait for services to stabilize before running the next step.
Managing Operations
Section titled “Managing Operations”Pause and Resume
Section titled “Pause and Resume”Pause an operation to temporarily stop it from executing. The schedule is preserved and resumes when you reactivate it.
- Pause: The operation stops executing on schedule
- Resume: The operation becomes active and executes at the next scheduled time
Manual Trigger
Section titled “Manual Trigger”Trigger an operation immediately, outside its schedule. Useful for testing or one-off executions. Manual triggers respect conditions and concurrency settings.
Run History
Section titled “Run History”Each operation tracks its execution history. For each run, you can see:
- Status (succeeded, failed, timed out, skipped)
- Start and completion time
- Duration
- Output or error message
- Whether it was triggered by schedule, manual action, or chain
- Any child runs it triggered
Deleting Operations
Section titled “Deleting Operations”Deleting an operation is a soft delete - the operation and its history are preserved but hidden from the active list.
Limits
Section titled “Limits”| Limit | Value |
|---|---|
| Max operations per organization | Configurable per plan |
| Command length | 4,096 characters |
| Timeout range | 30 seconds - 1 hour |
| Max retries | 3 |
| Retry delay range | 30 - 600 seconds |
| Chain depth | 5 levels |
| Post-action delay | 0 - 300 seconds |
| Auto-pause threshold | 5 consecutive failures |
Examples
Section titled “Examples”Nightly database backup
Section titled “Nightly database backup”Type: CommandSchedule: 0 2 * * * (daily at 2 AM)Timezone: America/New_YorkCommand: pg_dump -U postgres mydb | gzip > /backups/mydb-$(date +%Y%m%d).sql.gzTimeout: 30 minutesDeploy staging, then production
Section titled “Deploy staging, then production”Operation 1: Deploy Staging
Type: DeploySchedule: 0 9 * * 1-5 (weekdays at 9 AM)Application: my-app-stagingOperation 2: Deploy Production (triggered by Operation 1)
Type: DeployApplication: my-app-productionPost-action on Operation 1: On success, delay 300 secondsWeekly Docker cleanup
Section titled “Weekly Docker cleanup”Type: CommandSchedule: 0 4 * * 0 (Sundays at 4 AM)Command: docker system prune -af --filter "until=168h"Timeout: 10 minutesRestart with health check condition
Section titled “Restart with health check condition”Type: RestartSchedule: 0 6 * * * (daily at 6 AM)Condition: HTTP Check - https://myapp.com/health returns 200Application: my-appOnly restarts if the health check is currently passing. Skips the restart if the app is already down (to avoid masking the real issue).
Next Steps
Section titled “Next Steps”- GitHub Actions Integration to trigger operations from CI/CD
- Deployment Configuration to configure how deploys work
- Runner Servers to set up the runner agent on your servers