Skip to content

Jobs and schedules

Run a command once or on a schedule, then check its history.

A job is a named command that finishes, such as a database migration. A schedule runs a job at specified times. Jobs use an existing service's image, environment, networks, mounts, and secrets.

Jobs require Docker Compose or Podman Compose. Docker Swarm does not support them. Remote targets reject job operations they cannot support.

Define a job

Add a job to .config/mm.yaml. Use a module and service that already exist:

yaml
jobs:
  migrate:
    module: app
    service: web
    command: ["php", "artisan", "migrate", "--force"]
    timeout: 10m
    retry: { attempts: 3, backoff: 5s, max-backoff: 5m }
    history-limit: 100

Commands are lists of arguments, not shell strings. Check and apply the updated definitions:

sh
mm config validate
mm job schedule reconcile
mm job schedule reconcile --plan PLAN_HASH --yes

The first reconcile command previews changes; use its hash in the second. A deployment also updates job and schedule definitions. Removing a definition retains its run history.

Run and inspect

sh
mm job run migrate
mm job history migrate --limit 50
mm job status RUN_UUID
mm job cancel RUN_UUID
mm job retry RUN_UUID

Replace RUN_UUID with a run ID from the run command or history. Output is limited in size and redacted against configured secrets.

Add a schedule

This example runs the job at 02:00 UTC each day. Choose a job that is safe to repeat on that schedule:

yaml
schedules:
  nightly:
    job: migrate
    cron: "0 2 * * *"
    timezone: UTC
    enabled: true
    concurrency: forbid
    misfire: run-once

Reconcile after editing, then inspect or control the schedule:

sh
mm job schedule list
mm job schedule next nightly
mm job schedule run-now nightly
mm job schedule history nightly
mm job schedule disable nightly
mm job schedule enable nightly

Keep mm job schedule daemon running to process due jobs. Use a service manager for a persistent setup. In the terminal UI's Jobs page, t runs one controller cycle; defining a cron expression does not install an operating-system cron entry.

Timing and retries

  • Cron uses five fields: minute, hour, day of month, month, day of week. When both day fields are restricted, either may match.
  • Timezones use IANA names such as America/New_York. A skipped daylight-saving minute does not run; a repeated minute can run twice. Use UTC to avoid this.
  • concurrency: forbid prevents overlapping runs. allow permits them; replace requests cancellation of existing runs before adding another.
  • misfire: skip discards missed occurrences; run-once runs the latest. Bounded catch-up is available in the configuration reference.
  • Failed and timed-out runs can retry; cancelled runs do not. Retry delays increase up to max-backoff.

After an interruption

mm inspects an existing job container before relaunching it. If it cannot tell what happened, the run becomes unknown and automatic retries wait for a clear result. Inspect the run before manually retrying it.

A job can execute more than once after a failure. Make external side effects safe to repeat, for example by using MM_JOB_RUN_ID as a deduplication key. Jobs also receive MM_JOB_ATTEMPT and MM_JOB_FENCE_TOKEN.