[{"data":1,"prerenderedAt":732},["ShallowReactive",2],{"docs-nav":3,"docs:\u002Fdocs\u002Fjobs-and-schedules":139},[4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58,61,64,67,70,73,76,79,82,85,88,91,94,97,100,103,106,109,112,115,118,121,124,127,130,133,136],{"path":5,"title":6},"\u002Fdocs\u002Faccess-gating","Protect a local route",{"path":8,"title":9},"\u002Fdocs\u002Farchitecture\u002Fsecurity-and-trust","Security and trust",{"path":11,"title":12},"\u002Fdocs\u002Fconcepts\u002Fbuilds-and-deployments","Build and deploy",{"path":14,"title":15},"\u002Fdocs\u002Fconcepts\u002Fconfiguration-ownership","Where configuration belongs",{"path":17,"title":18},"\u002Fdocs\u002Fconcepts\u002Fenvironments-and-secrets","Environment values and secrets",{"path":20,"title":21},"\u002Fdocs\u002Fconcepts\u002Fmental-model","How projects fit together",{"path":23,"title":24},"\u002Fdocs\u002Fconcepts\u002Fplans-and-apply","Plans and apply",{"path":26,"title":27},"\u002Fdocs\u002Fconcepts\u002Ftargets-and-runtimes","Choose a target and runtime",{"path":29,"title":30},"\u002Fdocs\u002Fcontribute\u002Freleases","Publish a release",{"path":32,"title":33},"\u002Fdocs\u002Fdevelopment-mounts","Development mounts",{"path":35,"title":36},"\u002Fdocs\u002Fgetting-started","Getting started",{"path":38,"title":39},"\u002Fdocs\u002Fhelp\u002Ffaq","FAQ",{"path":41,"title":42},"\u002Fdocs\u002Fhelp\u002Ftroubleshooting","Troubleshooting",{"path":44,"title":45},"\u002Fdocs\u002Fhow-to\u002Fdeploy-production","Prepare a deployment environment",{"path":47,"title":48},"\u002Fdocs\u002Fhow-to\u002Fswarm-cluster","Run on a multi-node Swarm",{"path":50,"title":51},"\u002Fdocs","mm documentation",{"path":53,"title":54},"\u002Fdocs\u002Fjobs-and-schedules","Jobs and schedules",{"path":56,"title":57},"\u002Fdocs\u002Flocal-dashboard","Local dashboard",{"path":59,"title":60},"\u002Fdocs\u002Flocal-https","Local HTTPS",{"path":62,"title":63},"\u002Fdocs\u002Flocal-services","Local services",{"path":65,"title":66},"\u002Fdocs\u002Fmcp","Let an AI agent work on your project",{"path":68,"title":69},"\u002Fdocs\u002Fmulti-project-hosts","Run multiple projects on one host",{"path":71,"title":72},"\u002Fdocs\u002Fonboarding","Set up a project",{"path":74,"title":75},"\u002Fdocs\u002Fopenbao","Use OpenBao",{"path":77,"title":78},"\u002Fdocs\u002Fproject\u002Fcontributing","Contributing",{"path":80,"title":81},"\u002Fdocs\u002Fproject\u002Flicense","License",{"path":83,"title":84},"\u002Fdocs\u002Fproject\u002Fsecurity","Security",{"path":86,"title":87},"\u002Fdocs\u002Freference\u002Fcapability-matrix","Supported features and platforms",{"path":89,"title":90},"\u002Fdocs\u002Freference\u002Fcli","CLI command reference",{"path":92,"title":93},"\u002Fdocs\u002Freference\u002Fconfiguration","Configuration",{"path":95,"title":96},"\u002Fdocs\u002Freference\u002Fenvironment-variables","Environment variables",{"path":98,"title":99},"\u002Fdocs\u002Freference\u002Ferrors-and-exit-codes","Errors and exit codes",{"path":101,"title":102},"\u002Fdocs\u002Freference\u002Fknown-issues","Known limitations",{"path":104,"title":105},"\u002Fdocs\u002Fremote-access","Manage remote access",{"path":107,"title":108},"\u002Fdocs\u002Fremote-daemon","Set up a remote host",{"path":110,"title":111},"\u002Fdocs\u002Fruntime-observability","Status, logs, and commands",{"path":113,"title":114},"\u002Fdocs\u002Fsecret-delivery","Pass secrets to your app",{"path":116,"title":117},"\u002Fdocs\u002Fsecret-providers","Choose a secret store",{"path":119,"title":120},"\u002Fdocs\u002Fstart\u002Finstall","Install mm",{"path":122,"title":123},"\u002Fdocs\u002Fterminal-ui","Terminal UI",{"path":125,"title":126},"\u002Fdocs\u002Ftutorials\u002Fdotnet-web-api",".NET web API example",{"path":128,"title":129},"\u002Fdocs\u002Ftutorials\u002Ffirst-local-app","First local app",{"path":131,"title":132},"\u002Fdocs\u002Ftutorials\u002Flaravel-rust","Laravel and Rust example",{"path":134,"title":135},"\u002Fdocs\u002Ftutorials\u002Fnode-fullstack","Node full stack example",{"path":137,"title":138},"\u002Fdocs\u002Fvault","Use HashiCorp Vault",{"id":140,"title":54,"body":141,"description":725,"extension":726,"meta":727,"navigation":728,"path":53,"seo":729,"stem":730,"__hash__":731},"docs\u002Fdocs\u002Fjobs-and-schedules.md",{"type":142,"value":143,"toc":718},"minimark",[144,148,151,156,164,316,319,372,375,379,448,455,459,462,540,543,624,635,639,689,693,700,714],[145,146,147],"p",{},"A job is a named command that finishes, such as a database migration. A schedule\nruns a job at specified times. Jobs use an existing service's image, environment,\nnetworks, mounts, and secrets.",[145,149,150],{},"Jobs require Docker Compose or Podman Compose. Docker Swarm does not support\nthem. Remote targets reject job operations they cannot support.",[152,153,155],"h2",{"id":154},"define-a-job","Define a job",[145,157,158,159,163],{},"Add a job to ",[160,161,162],"code",{},".config\u002Fmm.yaml",". Use a module and service that already exist:",[165,166,171],"pre",{"className":167,"code":168,"language":169,"meta":170,"style":170},"language-yaml shiki shiki-themes mm","jobs:\n  migrate:\n    module: app\n    service: web\n    command: [\"php\", \"artisan\", \"migrate\", \"--force\"]\n    timeout: 10m\n    retry: { attempts: 3, backoff: 5s, max-backoff: 5m }\n    history-limit: 100\n","yaml","",[160,172,173,186,194,207,218,251,262,305],{"__ignoreMap":170},[174,175,178,182],"span",{"class":176,"line":177},"line",1,[174,179,181],{"class":180},"sWZmh","jobs",[174,183,185],{"class":184},"sIbZ0",":\n",[174,187,189,192],{"class":176,"line":188},2,[174,190,191],{"class":180},"  migrate",[174,193,185],{"class":184},[174,195,197,200,203],{"class":176,"line":196},3,[174,198,199],{"class":180},"    module",[174,201,202],{"class":184},":",[174,204,206],{"class":205},"sv8ni"," app\n",[174,208,210,213,215],{"class":176,"line":209},4,[174,211,212],{"class":180},"    service",[174,214,202],{"class":184},[174,216,217],{"class":205}," web\n",[174,219,221,224,226,229,232,235,238,240,243,245,248],{"class":176,"line":220},5,[174,222,223],{"class":180},"    command",[174,225,202],{"class":184},[174,227,228],{"class":184}," [",[174,230,231],{"class":205},"\"php\"",[174,233,234],{"class":184},",",[174,236,237],{"class":205}," \"artisan\"",[174,239,234],{"class":184},[174,241,242],{"class":205}," \"migrate\"",[174,244,234],{"class":184},[174,246,247],{"class":205}," \"--force\"",[174,249,250],{"class":184},"]\n",[174,252,254,257,259],{"class":176,"line":253},6,[174,255,256],{"class":180},"    timeout",[174,258,202],{"class":184},[174,260,261],{"class":205}," 10m\n",[174,263,265,268,270,273,276,278,282,284,287,289,292,294,297,299,302],{"class":176,"line":264},7,[174,266,267],{"class":180},"    retry",[174,269,202],{"class":184},[174,271,272],{"class":184}," {",[174,274,275],{"class":180}," attempts",[174,277,202],{"class":184},[174,279,281],{"class":280},"s1Wbj"," 3",[174,283,234],{"class":184},[174,285,286],{"class":180}," backoff",[174,288,202],{"class":184},[174,290,291],{"class":205}," 5s",[174,293,234],{"class":184},[174,295,296],{"class":180}," max-backoff",[174,298,202],{"class":184},[174,300,301],{"class":205}," 5m",[174,303,304],{"class":184}," }\n",[174,306,308,311,313],{"class":176,"line":307},8,[174,309,310],{"class":180},"    history-limit",[174,312,202],{"class":184},[174,314,315],{"class":280}," 100\n",[145,317,318],{},"Commands are lists of arguments, not shell strings. Check and apply the updated\ndefinitions:",[165,320,324],{"className":321,"code":322,"language":323,"meta":170,"style":170},"language-sh shiki shiki-themes mm","mm config validate\nmm job schedule reconcile\nmm job schedule reconcile --plan PLAN_HASH --yes\n","sh",[160,325,326,338,351],{"__ignoreMap":170},[174,327,328,332,335],{"class":176,"line":177},[174,329,331],{"class":330},"svrjQ","mm",[174,333,334],{"class":205}," config",[174,336,337],{"class":205}," validate\n",[174,339,340,342,345,348],{"class":176,"line":188},[174,341,331],{"class":330},[174,343,344],{"class":205}," job",[174,346,347],{"class":205}," schedule",[174,349,350],{"class":205}," reconcile\n",[174,352,353,355,357,359,362,366,369],{"class":176,"line":196},[174,354,331],{"class":330},[174,356,344],{"class":205},[174,358,347],{"class":205},[174,360,361],{"class":205}," reconcile",[174,363,365],{"class":364},"sbRf1"," --plan",[174,367,368],{"class":205}," PLAN_HASH",[174,370,371],{"class":364}," --yes\n",[145,373,374],{},"The first reconcile command previews changes; use its hash in the second.\nA deployment also updates job and schedule definitions. Removing a definition\nretains its run history.",[152,376,378],{"id":377},"run-and-inspect","Run and inspect",[165,380,382],{"className":321,"code":381,"language":323,"meta":170,"style":170},"mm job run migrate\nmm job history migrate --limit 50\nmm job status RUN_UUID\nmm job cancel RUN_UUID\nmm job retry RUN_UUID\n",[160,383,384,396,414,426,437],{"__ignoreMap":170},[174,385,386,388,390,393],{"class":176,"line":177},[174,387,331],{"class":330},[174,389,344],{"class":205},[174,391,392],{"class":205}," run",[174,394,395],{"class":205}," migrate\n",[174,397,398,400,402,405,408,411],{"class":176,"line":188},[174,399,331],{"class":330},[174,401,344],{"class":205},[174,403,404],{"class":205}," history",[174,406,407],{"class":205}," migrate",[174,409,410],{"class":364}," --limit",[174,412,413],{"class":280}," 50\n",[174,415,416,418,420,423],{"class":176,"line":196},[174,417,331],{"class":330},[174,419,344],{"class":205},[174,421,422],{"class":205}," status",[174,424,425],{"class":205}," RUN_UUID\n",[174,427,428,430,432,435],{"class":176,"line":209},[174,429,331],{"class":330},[174,431,344],{"class":205},[174,433,434],{"class":205}," cancel",[174,436,425],{"class":205},[174,438,439,441,443,446],{"class":176,"line":220},[174,440,331],{"class":330},[174,442,344],{"class":205},[174,444,445],{"class":205}," retry",[174,447,425],{"class":205},[145,449,450,451,454],{},"Replace ",[160,452,453],{},"RUN_UUID"," with a run ID from the run command or history. Output is\nlimited in size and redacted against configured secrets.",[152,456,458],{"id":457},"add-a-schedule","Add a schedule",[145,460,461],{},"This example runs the job at 02:00 UTC each day. Choose a job that is safe to\nrepeat on that schedule:",[165,463,465],{"className":167,"code":464,"language":169,"meta":170,"style":170},"schedules:\n  nightly:\n    job: migrate\n    cron: \"0 2 * * *\"\n    timezone: UTC\n    enabled: true\n    concurrency: forbid\n    misfire: run-once\n",[160,466,467,474,481,490,500,510,520,530],{"__ignoreMap":170},[174,468,469,472],{"class":176,"line":177},[174,470,471],{"class":180},"schedules",[174,473,185],{"class":184},[174,475,476,479],{"class":176,"line":188},[174,477,478],{"class":180},"  nightly",[174,480,185],{"class":184},[174,482,483,486,488],{"class":176,"line":196},[174,484,485],{"class":180},"    job",[174,487,202],{"class":184},[174,489,395],{"class":205},[174,491,492,495,497],{"class":176,"line":209},[174,493,494],{"class":180},"    cron",[174,496,202],{"class":184},[174,498,499],{"class":205}," \"0 2 * * *\"\n",[174,501,502,505,507],{"class":176,"line":220},[174,503,504],{"class":180},"    timezone",[174,506,202],{"class":184},[174,508,509],{"class":205}," UTC\n",[174,511,512,515,517],{"class":176,"line":253},[174,513,514],{"class":180},"    enabled",[174,516,202],{"class":184},[174,518,519],{"class":280}," true\n",[174,521,522,525,527],{"class":176,"line":264},[174,523,524],{"class":180},"    concurrency",[174,526,202],{"class":184},[174,528,529],{"class":205}," forbid\n",[174,531,532,535,537],{"class":176,"line":307},[174,533,534],{"class":180},"    misfire",[174,536,202],{"class":184},[174,538,539],{"class":205}," run-once\n",[145,541,542],{},"Reconcile after editing, then inspect or control the schedule:",[165,544,546],{"className":321,"code":545,"language":323,"meta":170,"style":170},"mm job schedule list\nmm job schedule next nightly\nmm job schedule run-now nightly\nmm job schedule history nightly\nmm job schedule disable nightly\nmm job schedule enable nightly\n",[160,547,548,559,573,586,598,611],{"__ignoreMap":170},[174,549,550,552,554,556],{"class":176,"line":177},[174,551,331],{"class":330},[174,553,344],{"class":205},[174,555,347],{"class":205},[174,557,558],{"class":205}," list\n",[174,560,561,563,565,567,570],{"class":176,"line":188},[174,562,331],{"class":330},[174,564,344],{"class":205},[174,566,347],{"class":205},[174,568,569],{"class":205}," next",[174,571,572],{"class":205}," nightly\n",[174,574,575,577,579,581,584],{"class":176,"line":196},[174,576,331],{"class":330},[174,578,344],{"class":205},[174,580,347],{"class":205},[174,582,583],{"class":205}," run-now",[174,585,572],{"class":205},[174,587,588,590,592,594,596],{"class":176,"line":209},[174,589,331],{"class":330},[174,591,344],{"class":205},[174,593,347],{"class":205},[174,595,404],{"class":205},[174,597,572],{"class":205},[174,599,600,602,604,606,609],{"class":176,"line":220},[174,601,331],{"class":330},[174,603,344],{"class":205},[174,605,347],{"class":205},[174,607,608],{"class":205}," disable",[174,610,572],{"class":205},[174,612,613,615,617,619,622],{"class":176,"line":253},[174,614,331],{"class":330},[174,616,344],{"class":205},[174,618,347],{"class":205},[174,620,621],{"class":205}," enable",[174,623,572],{"class":205},[145,625,626,627,630,631,634],{},"Keep ",[160,628,629],{},"mm job schedule daemon"," running to process due jobs. Use a service manager\nfor a persistent setup. In the terminal UI's Jobs page, ",[160,632,633],{},"t"," runs one controller\ncycle; defining a cron expression does not install an operating-system cron entry.",[152,636,638],{"id":637},"timing-and-retries","Timing and retries",[640,641,642,646,653,667,683],"ul",{},[643,644,645],"li",{},"Cron uses five fields: minute, hour, day of month, month, day of week. When\nboth day fields are restricted, either may match.",[643,647,648,649,652],{},"Timezones use IANA names such as ",[160,650,651],{},"America\u002FNew_York",". A skipped daylight-saving\nminute does not run; a repeated minute can run twice. Use UTC to avoid this.",[643,654,655,658,659,662,663,666],{},[160,656,657],{},"concurrency: forbid"," prevents overlapping runs. ",[160,660,661],{},"allow"," permits them;\n",[160,664,665],{},"replace"," requests cancellation of existing runs before adding another.",[643,668,669,672,673,676,677,682],{},[160,670,671],{},"misfire: skip"," discards missed occurrences; ",[160,674,675],{},"run-once"," runs the latest.\nBounded catch-up is available in the ",[678,679,681],"a",{"href":680},".\u002Freference\u002Fconfiguration#jobs-and-schedules","configuration reference",".",[643,684,685,686,682],{},"Failed and timed-out runs can retry; cancelled runs do not. Retry delays\nincrease up to ",[160,687,688],{},"max-backoff",[152,690,692],{"id":691},"after-an-interruption","After an interruption",[145,694,695,696,699],{},"mm inspects an existing job container before relaunching it. If it cannot tell\nwhat happened, the run becomes ",[160,697,698],{},"unknown"," and automatic retries wait for a clear\nresult. Inspect the run before manually retrying it.",[145,701,702,703,706,707,710,711,682],{},"A job can execute more than once after a failure. Make external side effects\nsafe to repeat, for example by using ",[160,704,705],{},"MM_JOB_RUN_ID"," as a deduplication key.\nJobs also receive ",[160,708,709],{},"MM_JOB_ATTEMPT"," and ",[160,712,713],{},"MM_JOB_FENCE_TOKEN",[715,716,717],"style",{},"html pre.shiki code .sWZmh, html code.shiki .sWZmh{--shiki-default:var(--mm-code-key)}html pre.shiki code .sIbZ0, html code.shiki .sIbZ0{--shiki-default:var(--mm-code-punctuation)}html pre.shiki code .sv8ni, html code.shiki .sv8ni{--shiki-default:var(--mm-code-string)}html pre.shiki code .s1Wbj, html code.shiki .s1Wbj{--shiki-default:var(--mm-code-constant)}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .svrjQ, html code.shiki .svrjQ{--shiki-default:var(--mm-code-function)}html pre.shiki code .sbRf1, html code.shiki .sbRf1{--shiki-default:var(--mm-code-option)}",{"title":170,"searchDepth":188,"depth":188,"links":719},[720,721,722,723,724],{"id":154,"depth":188,"text":155},{"id":377,"depth":188,"text":378},{"id":457,"depth":188,"text":458},{"id":637,"depth":188,"text":638},{"id":691,"depth":188,"text":692},"Run a command once or on a schedule, then check its history.","md",{},true,{"title":54,"description":725},"docs\u002Fjobs-and-schedules","MtVRens8PJbneDgqdd8zGb4o048M29cHoRKBde0KPs4",1794512545909]