Guides

Scheduled jobs

Run commands on a schedule (cron), once, or on demand, on your servers or inside one of your app's containers, and tune the built-in maintenance jobs Synq runs for you.

Jobs are tasks that run on a schedule on your install: the maintenance Synq does for you, and commands you want to run yourself, such as a nightly database dump, a cache warm-up or a cleanup script. Open Jobs in the sidebar (under Infrastructure).

The page has three sections:

  • System jobs: built-in maintenance on this instance.
  • Custom jobs: commands you run on your servers or in your apps' containers.
  • Backup schedules: the automatic backups of your projects and services, listed read-only. They are managed on each project's Backups tab (Manage in Backups).

At a glance counts all jobs and how many are running, failed, scheduled or disabled. Every run is recorded with its trigger (schedule or manual), result, duration and output.

Built-in jobs

Synq keeps these running for you. Each row shows its Schedule, Next run and Last run, with Run now, Edit schedule, Enable / Disable and Logs. Changing a built-in job needs an instance administrator. You can't delete a built-in job; disable it instead.

JobWhat it doesDefault schedule
SSL certificate renewalRenews Let's Encrypt certificates before they expiredaily at 03:17
Orphaned resource cleanupReclaims leftovers from a failed teardownhourly
Deployment artifact cleanupRemoves old release images beyond each project's retentiondaily at 04:23
Docker build-cache garbage collectionKeeps the build cache on each Docker host within about 10 GBdaily at 04:37
Docker cleanupRemoves unused Docker images, containers, build cache and (if chosen) volumes. Off by default; set it up on a server's Docker tabSundays at 03:41
Panel database backupBacks up the control-plane database to a backup destination. Off by default; set it up in Settings, Instancedaily at 02:11
Backup retention pruneDeletes backups past their retentionhourly
Audit log pruneDeletes audit entries older than the workspace's retentiondaily at 04:07
Deployment reconcileSettles deploys interrupted by a connection blipevery 10 minutes
Domain DNS verificationRe-checks domains still waiting for DNSevery 13 minutes
Update scan, Native-module update scan, Managed-container update scanLook for new versions of Synq's parts and of the edge and mail containersevery 6 hours
Resource usage sampling, Traffic analytics collection, Container health watchCollect the numbers behind monitoringfrom every minute to twice an hour
One-time job dispatcherStarts custom jobs scheduled to run onceevery minute
Job run history pruneDeletes old job runsdaily at 04:23

There are a few more housekeeping jobs (prunes of analytics, usage samples, incidents, webhook events and pending grants). The exact list depends on your install; the page shows all of them.

Turn Docker cleanup and panel backups on where they are configured

Both need settings the Jobs page doesn't have (what to remove and on which servers; where to store the backup). Turn them on from their own screens, then use Jobs to watch their runs. The Docker cleanup card on a server's Docker tab has an Open in Jobs link that leads here; for panel backups, find the Panel database backup row on this page.

Create a custom job

Start a new job

In Jobs, press New job (or Create job when you have none).

Basics

Give it a Name (for example "Nightly DB vacuum") and the Command to run. Then choose Run inside:

  • Host: the command runs over SSH on the Target servers you tick. It can also start a throwaway container, for example docker run --rm postgres:16 pg_dump ....
  • A project's service: the command runs inside that service's running container. See below.

Schedule

Pick When to run:

ChoiceMeaning
On a scheduleA 5-field cron in Schedule (cron). Synq checks it when you save and shows the next run.
OnceAt the date and time in Run at.
ManualOnly when triggered: Run now, a job it depends on, or an event.

Reliability, environment and triggers (optional)

SectionFields
ReliabilityTimeout (s) stops the command after that long (up to 24 hours). Max attempts (1 to 10) and Backoff (s) retry a failed run; all attempts land in one run.
EnvironmentEnvironment variables (Add variable, Paste .env or Upload .env) and Secrets, which are encrypted and only decrypted when the job runs. Both are exported before your command.
Dependencies & triggersRun after: start when the chosen jobs succeed. Event triggers: start on Deploy succeeded, Deploy failed, Backup succeeded, Backup failed, Restore completed, SSL renewal failed or Domain verification failed.
NotificationsWhich channels hear about running, success or failed, overriding your global notification settings for this job.

Create it

Check the Summary and press Create job. Open the job to see its Overview and Runs, press Run now, Edit or Delete it. Logs streams a run's output live while it runs.

Run a job inside an app's container

Choose Run inside, A project's service, then the Project and the Service. The command runs with docker exec in that service's running container, on the server the project is deployed to. Use it for tasks that need the app's own code, tools and environment:

# A Laravel scheduler tick
php artisan schedule:run

# A Django management command
python manage.py clearsessions

# A Node script shipped with the app
node scripts/send-digest.js

Things to know:

  • The server is taken from the project; you don't pick one. A container job always targets exactly one server.
  • The service must be running when the job fires, or the run fails.
  • The output appears when the command finishes (a host job streams it line by line).
  • Without a Timeout, a container job is stopped after 1 hour.
  • Saving, running or deleting it needs write access to that project, on top of the server access every job needs.
  • To move a job back to the host, edit it and choose Host.

Schedules (cron), in plain terms

A schedule is a standard 5-field cron string, in the Synq server's time zone (UTC in the standard install):

┌───────── minute (0-59)
│ ┌─────── hour (0-23)
│ │ ┌───── day of month (1-31)
│ │ │ ┌─── month (1-12)
│ │ │ │ ┌─ day of week (0-6, Sunday is 0)
* * * * *
CronWhen
0 3 * * *every day at 03:00
*/15 * * * *every 15 minutes
0 * * * *every hour, on the hour
0 2 * * 0every Sunday at 02:00
30 4 1 * *04:30 on the 1st of each month

Run now is recorded too

A run started with Run now is saved in the history like a scheduled one, marked as manual, so you always have a full record.

Who can manage jobs

  • Built-in jobs: instance administrators change their schedule, turn them on or off and run them.
  • Custom jobs: you need admin access to every target server (owners, admins and members have it; restricted members need a server grant with admin). A job that runs inside a container also needs write access to its project. People who can't reach a job's servers don't see it.

CLI

Use synq job (alias jobs) with your self-hosted connection context:

synq job list
synq job create --name weekly-sync --server <server-id> \
  --command 'cd /srv/app && npm run db:sync' --cron '17 4 * * 1'
synq job get <key>
synq job update <key> --no-enabled
synq job update <key> --enabled --cron '0 3 * * *'
synq job run <key> --follow
synq job runs <key> --limit 10
synq job logs <run-id> --follow
synq job delete <key> --yes

Jobs also work with synq --native-config <file> job ... through the native SDK.

Use the job key from list or create, not its database ID. For a one-time job, pass --schedule once --at <ISO-timestamp>. For manual execution only, pass --schedule manual. Recurring jobs use --cron.

Both create and update accept --file <path> containing a JSON Jobs API body. Use it for env, secrets, serverIds, retry, timeoutMs, dependsOn, triggerEvents, notifyConfig, or a container target, or to supply the entire job configuration. Explicit flags override file values. Updates send only supplied fields. Keep files containing secrets private. The API encrypts secrets at rest.

A job that runs inside a container sets both projectId and serviceId (the server is derived from the project):

{
  "label": "Laravel scheduler",
  "command": "php artisan schedule:run",
  "scheduleType": "recurring",
  "cronExpression": "* * * * *",
  "projectId": "proj_123",
  "serviceId": "svc_456"
}
synq job create --file scheduler.json

Sending "projectId": null, "serviceId": null in an update moves the job back to the host.

--json returns API data without the envelope. Followed runs emit JSON events. Without --follow, run returns a custom run ID immediately. With --follow, the CLI waits for the outcome and exits nonzero on failure or an interrupted stream. Built-in jobs return their summary directly. logs without --follow shows stored output, or the full run record with --json.

On this page