The one cron job MagicPost needs, every task it runs, how posts are sent in cron or worker mode, and how to check that it is working.
MagicPost runs all of its background work from the Laravel scheduler. A single cron job that starts the scheduler every minute is enough to publish posts, renew channel tokens, deliver webhooks, read feeds and more. If it does not run, scheduled posts simply stop going out.
Without the cron job nothing is published. Add it as soon as the install finishes.
Under PHP-FPM or LiteSpeed the web server’s PHP is not the command-line PHP. MagicPost uses the command-line php from the same PHP installation when it can find one, and plain php otherwise. If the command it shows does not run, ask your host for the path of the command-line PHP and use that instead.
In cPanel, open Cron Jobs in the Advanced section.
Cron Jobs in the Advanced section of cPanel
2
Choose the interval
Under Add New Cron Job, open Common Settings and choose Once Per Minute. If your cPanel has no such option, type * in each of the Minute, Hour, Day, Month and Weekday fields.
3
Paste the command
Paste the command from MagicPost into the Command field and click Add New Cron Job.
Run crontab -e as the user that owns the application files, paste the full crontab line from the Sending card, and save.
If your host only allows a five-minute interval, the cron job still works, but posts go out up to five minutes late. System health treats the cron job as stopped when the last run is more than five minutes old, so with a five-minute interval it can flag the job between runs.
Every task runs inside the schedule:run process, so the scheduler does not need proc_open. Tasks that overlap themselves are guarded with cache locks, which is why System health warns when CACHE_STORE is array or null.
Task
When
What it does
publishing:heartbeat
Every minute
Records the time of the run. System health reads it for the Cron job line.
publishing:dispatch
Every minute
Claims posts that are due and queues them. It also closes off posts that can never go out and posts held back longer than Wait for a channel for up to.
publishing:work:1, publishing:work:2
Every minute, in scheduler mode only
Two lanes that send queued jobs, so one long upload does not stall every other post.
publishing:deliver-webhooks
Every minute
Sends webhook deliveries that are due and clears out old ones.
telegram:poll
Every minute, only while Telegram is set to polling
Fetches waiting Telegram updates for a site that Telegram cannot reach with a webhook. See Set up Telegram.
publishing:recover
Every 5 minutes
Returns posts that were left in the sending state longer than Pick up a stalled send after.
publishing:check-feeds
Every 5 minutes
Reads the RSS feeds that are due and turns new articles into posts.
media:sweep-generations
Every 5 minutes
Picks up AI image and video requests that a crashed run left behind, and releases the credits of requests that never finished.
publishing:recurring
Hourly
Creates the upcoming occurrences of recurring posts.
publishing:refresh-tokens
Hourly
Renews channel access tokens that expire within 24 hours.
publishing:sync-metrics
Hourly, only while Collect analytics is on
Reads follower and post figures from the networks.
publishing:recycle-evergreen
Hourly, at 20 minutes past
Lines up the next repeat of every evergreen post that is due one.
publishing:check-channels
Hourly, at 30 minutes past
Checks channels that have posts due in the next two days, so a revoked token is found before a post fails.
whatsapp:close-abandoned
Hourly
Ends WhatsApp linking sessions that nobody finished.
credits:release-expired-holds
Hourly, at 45 minutes past
Releases credit holds that passed their expiry.
credits:refresh-allowances
Hourly, at 50 minutes past
Refreshes the monthly allowance of yearly and lifetime plans and ends unlimited credits whose plan has lapsed.
publishing:prune-notifications
Daily at 03:15, only while Keep read notifications is not set to For good
Deletes read publishing notifications older than the retention you chose. Unread ones are kept.
Under Admin → Publishing → Settings, the Sending card has a Posts are sent by choice.
The scheduler
A queue worker
The default, for hosts that only offer cron. Every minute, the two publishing:work lanes process queued jobs for the number of seconds set in Each pass sends for. The value must be between 10 and 55 seconds, and the default is 45, so a pass ends before the next one begins. Lower it if your host stops long cron jobs.
For servers that keep a queue worker running under Supervisor or systemd. The scheduler stops running the publishing:work lanes, and you run this command from the folder MagicPost is installed in:
The cron job is still required in this mode, because the scheduler decides which posts are due and queues them.
Both modes use the queue named by QUEUE_CONNECTION in .env, which defaults to database. System health reports the null driver as a problem, because it throws jobs away, and the sync driver as a warning, because each post would then be sent inside the request that queued it. Set QUEUE_CONNECTION=database unless you run another queue backend on purpose.Hand out at most on the same page limits how many posts are handed to the queue per minute. Posts due at the same moment beyond that limit go out over the following minutes. See Publishing settings for the retry, waiting and upload limits.
The Sending card shows Last ran with the time of the last scheduler run, or Has not run yet.
System health shows the Cron job line as passed, with the time of the last run. It fails with “The scheduler has never run” or “The scheduler last ran” when the last run is missing or more than five minutes old.
The Queue line reports jobs that have waited more than ten minutes, and says whether the cause is a missing worker or a slow scheduler.
The cron job is missing or its command is wrong. Check the path of the application and of the command-line PHP, and make sure the cron user can read the application folder.
The cron job runs but posts stay scheduled
Open System health and read the Queue, Waiting posts and Stalled sends lines. A channel that is paused, needs reconnecting, or belongs to a network that is switched off holds its due posts for up to the Wait for a channel for up to limit.
The Locks line warns about the cache
Set CACHE_STORE=database or CACHE_STORE=file in .env. The array and null stores forget everything between requests, so overlapping scheduler runs cannot be kept apart.
{"docsConfig":{"theme":"maple","$schema":"https://mintlify.com/docs.json","name":"MagicPost","colors":{"primary":"#0353A4","light":"#8FBCE8","dark":"#04437F"},"logo":{"light":"https://mintcdn.com/magic-post/wSf-YhNVjpL3AqP0/logo/light.png?fit=max\u0026auto=format\u0026n=wSf-YhNVjpL3AqP0\u0026q=85\u0026s=4c828f56d35df0facd10dc7f9d6d379c","dark":"https://mintcdn.com/magic-post/wSf-YhNVjpL3AqP0/logo/dark.png?fit=max\u0026auto=format\u0026n=wSf-YhNVjpL3AqP0\u0026q=85\u0026s=91d35a12098bb8caf9f01f160d194219"},"favicon":"https://mintcdn.com/magic-post/wSf-YhNVjpL3AqP0/logo/favicon.ico?fit=max\u0026auto=format\u0026n=wSf-YhNVjpL3AqP0\u0026q=85\u0026s=78d0d87380e878eb1f895a9be00ed327","navbar":{"links":[{"href":"https://support.berkine.dev/","label":"Support"}],"primary":{"type":"button","label":"Buy MagicPost","href":"https://berkine.dev/scripts/magicpost"}},"footer":{"socials":{"x":"https://x.com/mintlify","youtube":"https://x.com/mintlify","linkedin":"https://linkedin.com/company/mintlify"}},"seo":{"indexing":"all"},"styling":{"latex":false},"navigation":{"global":{"anchors":[{"anchor":"Buy MagicPost","icon":"box-open","href":"https://berkine.dev/scripts/magicpost"},{"anchor":"Support Tickets","icon":"square-info","href":"https://support.berkine.dev/"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"magic-post","hasAudioNarration":false,"actualSubdomain":"magic-post","customDomains":[],"gitSource":{"type":"github","owner":"berkinemagicpost","repo":"magicpost-docs","deployBranch":"main","contentDirectory":"","isPrivate":false,"mountPath":"","label":"","_id":"6ae8efd8751535910ce167c9"},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6af0bc9b2cd45511358481b7","clientVersion":"0.0.4111","searchFilterCounts":[{"language":"default","tag":"SaaS \u0026 billing","count":26},{"language":"default","tag":"User guide","count":23},{"language":"default","tag":"Admin panel","count":18},{"language":"default","tag":"Publishing channels","count":15},{"language":"default","tag":"Payment gateways","count":15},{"language":"default","tag":"Account","count":11},{"language":"default","tag":"Integrations","count":10},{"language":"default","tag":"Installation \u0026 updates","count":8},{"language":"default","tag":"Advanced","count":7},{"language":"default","tag":"Troubleshooting","count":6}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"installation/cron-and-queue","slug":"/installation/cron-and-queue","pageMetadata":{"title":"Cron and queue","description":"The one cron job MagicPost needs, every task it runs, how posts are sent in cron or worker mode, and how to check that it is working.","href":"/installation/cron-and-queue"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"The one cron job MagicPost needs, every task it runs, how posts are sent in cron or worker mode, and how to check that it is working.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{Accordion,AccordionGroup,CodeBlock,Frame,Heading,Note,OptimizedImage,Step,Steps,Tab,Table,Tabs,Tip,Warning}=_components;if(!Accordion)_missingMdxReference(`Accordion`,true);if(!AccordionGroup)_missingMdxReference(`AccordionGroup`,true);if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Frame)_missingMdxReference(`Frame`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Note)_missingMdxReference(`Note`,true);if(!OptimizedImage)_missingMdxReference(`OptimizedImage`,true);if(!Step)_missingMdxReference(`Step`,true);if(!Steps)_missingMdxReference(`Steps`,true);if(!Tab)_missingMdxReference(`Tab`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Tabs)_missingMdxReference(`Tabs`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(_components.p,{children:`MagicPost runs all of its background work from the Laravel scheduler. A single cron job that starts the scheduler every minute is enough to publish posts, renew channel tokens, deliver webhooks, read feeds and more. If it does not run, scheduled posts simply stop going out.`}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`Without the cron job nothing is published. Add it as soon as the install finishes.`})}),`\n`,_jsx(Heading,{level:`2`,id:`the-cron-command`,children:`The cron command`}),`\n`,_jsx(_components.p,{children:`MagicPost builds the exact command for your server, with the application path and the PHP binary it found. You can copy it from two places:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`The last screen of the `,_jsx(_components.a,{href:`/installation/web-installer`,children:`web installer`}),`, under `,_jsx(_components.strong,{children:`One last step: add the cron job`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Admin → Publishing → Settings, in the `,_jsx(_components.strong,{children:`Sending`}),` card, next to `,_jsx(_components.strong,{children:`Cron job`}),`. Click `,_jsx(_components.strong,{children:`Copy`}),` for the command alone, or `,_jsx(_components.strong,{children:`Copy the crontab line`}),` for the full line.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`The crontab line looks like this. Your path and PHP binary will differ, so copy yours from the application.`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`*`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` *`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` *`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` *`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` *`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` cd /home/USERNAME/public_html \u0026\u0026 `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`/usr/local/bin/php`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` artisan`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` schedule:run`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` >>`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` /dev/null`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` 2>\u00261`})]}),`\n`]})})}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`Under PHP-FPM or LiteSpeed the web server’s PHP is not the command-line PHP. MagicPost uses the command-line `,_jsx(_components.code,{children:`php`}),` from the same PHP installation when it can find one, and plain `,_jsx(_components.code,{children:`php`}),` otherwise. If the command it shows does not run, ask your host for the path of the command-line PHP and use that instead.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`add-the-cron-job`,children:`Add the cron job`}),`\n`,_jsxs(Tabs,{children:[_jsx(Tab,{title:`cPanel`,id:`cpanel`,children:_jsxs(Steps,{children:[_jsxs(Step,{title:`Open Cron Jobs`,children:[_jsxs(_components.p,{children:[`In cPanel, open `,_jsx(_components.strong,{children:`Cron Jobs`}),` in the `,_jsx(_components.strong,{children:`Advanced`}),` section.`]}),_jsx(Frame,{caption:`Cron Jobs in the Advanced section of cPanel`,children:_jsx(OptimizedImage,{src:`https://mintcdn.com/magic-post/a8bg4xDpTuAYb58l/images/advanced/cron/cron-1.png?fit=max\u0026auto=format\u0026n=a8bg4xDpTuAYb58l\u0026q=85\u0026s=b5eda86147db6799cb8d9a0cff7de90b`,alt:`cPanel Advanced section with Cron Jobs highlighted`,\"data-og-width\":`1014`,width:`1014`,\"data-og-height\":`267`,height:`267`,\"data-path\":`images/advanced/cron/cron-1.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/magic-post/a8bg4xDpTuAYb58l/images/advanced/cron/cron-1.png?w=280\u0026fit=max\u0026auto=format\u0026n=a8bg4xDpTuAYb58l\u0026q=85\u0026s=6be2b489bf96a2778e6bcd1144187bf1 280w, https://mintcdn.com/magic-post/a8bg4xDpTuAYb58l/images/advanced/cron/cron-1.png?w=560\u0026fit=max\u0026auto=format\u0026n=a8bg4xDpTuAYb58l\u0026q=85\u0026s=055a3dd86303a7ccb092703ae914f861 560w, https://mintcdn.com/magic-post/a8bg4xDpTuAYb58l/images/advanced/cron/cron-1.png?w=840\u0026fit=max\u0026auto=format\u0026n=a8bg4xDpTuAYb58l\u0026q=85\u0026s=b319e00ad145c423793a1aa3720655b0 840w, https://mintcdn.com/magic-post/a8bg4xDpTuAYb58l/images/advanced/cron/cron-1.png?w=1100\u0026fit=max\u0026auto=format\u0026n=a8bg4xDpTuAYb58l\u0026q=85\u0026s=bac5d367247344e4abb2d353fe8a2d5d 1100w, https://mintcdn.com/magic-post/a8bg4xDpTuAYb58l/images/advanced/cron/cron-1.png?w=1650\u0026fit=max\u0026auto=format\u0026n=a8bg4xDpTuAYb58l\u0026q=85\u0026s=a56fd4ddcea3ac6ec7e904660b1f922f 1650w, https://mintcdn.com/magic-post/a8bg4xDpTuAYb58l/images/advanced/cron/cron-1.png?w=2500\u0026fit=max\u0026auto=format\u0026n=a8bg4xDpTuAYb58l\u0026q=85\u0026s=0de9279c59e5dce5b66894ffa2012ed1 2500w`})})]}),_jsx(Step,{title:`Choose the interval`,children:_jsxs(_components.p,{children:[`Under `,_jsx(_components.strong,{children:`Add New Cron Job`}),`, open `,_jsx(_components.strong,{children:`Common Settings`}),` and choose `,_jsx(_components.strong,{children:`Once Per Minute`}),`. If your cPanel has no such option, type `,_jsx(_components.code,{children:`*`}),` in each of the `,_jsx(_components.strong,{children:`Minute`}),`, `,_jsx(_components.strong,{children:`Hour`}),`, `,_jsx(_components.strong,{children:`Day`}),`, `,_jsx(_components.strong,{children:`Month`}),` and `,_jsx(_components.strong,{children:`Weekday`}),` fields.`]})}),_jsx(Step,{title:`Paste the command`,children:_jsxs(_components.p,{children:[`Paste the command from MagicPost into the `,_jsx(_components.strong,{children:`Command`}),` field and click `,_jsx(_components.strong,{children:`Add New Cron Job`}),`.`]})})]})}),_jsx(Tab,{title:`Crontab on a VPS`,id:`crontab-on-a-vps`,children:_jsxs(_components.p,{children:[`Run `,_jsx(_components.code,{children:`crontab -e`}),` as the user that owns the application files, paste the full crontab line from the `,_jsx(_components.strong,{children:`Sending`}),` card, and save.`]})})]}),`\n`,_jsx(Tip,{children:_jsxs(_components.p,{children:[`If your host only allows a five-minute interval, the cron job still works, but posts go out up to five minutes late. `,_jsx(_components.strong,{children:`System health`}),` treats the cron job as stopped when the last run is more than five minutes old, so with a five-minute interval it can flag the job between runs.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`what-the-scheduler-runs`,children:`What the scheduler runs`}),`\n`,_jsxs(_components.p,{children:[`Every task runs inside the `,_jsx(_components.code,{children:`schedule:run`}),` process, so the scheduler does not need `,_jsx(_components.code,{children:`proc_open`}),`. Tasks that overlap themselves are guarded with cache locks, which is why `,_jsx(_components.strong,{children:`System health`}),` warns when `,_jsx(_components.code,{children:`CACHE_STORE`}),` is `,_jsx(_components.code,{children:`array`}),` or `,_jsx(_components.code,{children:`null`}),`.`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Task`}),_jsx(_components.th,{children:`When`}),_jsx(_components.th,{children:`What it does`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`publishing:heartbeat`})}),_jsx(_components.td,{children:`Every minute`}),_jsxs(_components.td,{children:[`Records the time of the run. `,_jsx(_components.strong,{children:`System health`}),` reads it for the `,_jsx(_components.strong,{children:`Cron job`}),` line.`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`publishing:dispatch`})}),_jsx(_components.td,{children:`Every minute`}),_jsxs(_components.td,{children:[`Claims posts that are due and queues them. It also closes off posts that can never go out and posts held back longer than `,_jsx(_components.strong,{children:`Wait for a channel for up to`}),`.`]})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`publishing:work:1`}),`, `,_jsx(_components.code,{children:`publishing:work:2`})]}),_jsx(_components.td,{children:`Every minute, in scheduler mode only`}),_jsx(_components.td,{children:`Two lanes that send queued jobs, so one long upload does not stall every other post.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`publishing:deliver-webhooks`})}),_jsx(_components.td,{children:`Every minute`}),_jsx(_components.td,{children:`Sends webhook deliveries that are due and clears out old ones.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`telegram:poll`})}),_jsx(_components.td,{children:`Every minute, only while Telegram is set to polling`}),_jsxs(_components.td,{children:[`Fetches waiting Telegram updates for a site that Telegram cannot reach with a webhook. See `,_jsx(_components.a,{href:`/channels/telegram/setup`,children:`Set up Telegram`}),`.`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`publishing:recover`})}),_jsx(_components.td,{children:`Every 5 minutes`}),_jsxs(_components.td,{children:[`Returns posts that were left in the sending state longer than `,_jsx(_components.strong,{children:`Pick up a stalled send after`}),`.`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`publishing:check-feeds`})}),_jsx(_components.td,{children:`Every 5 minutes`}),_jsx(_components.td,{children:`Reads the RSS feeds that are due and turns new articles into posts.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`media:sweep-generations`})}),_jsx(_components.td,{children:`Every 5 minutes`}),_jsx(_components.td,{children:`Picks up AI image and video requests that a crashed run left behind, and releases the credits of requests that never finished.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`publishing:recurring`})}),_jsx(_components.td,{children:`Hourly`}),_jsx(_components.td,{children:`Creates the upcoming occurrences of recurring posts.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`publishing:refresh-tokens`})}),_jsx(_components.td,{children:`Hourly`}),_jsx(_components.td,{children:`Renews channel access tokens that expire within 24 hours.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`publishing:sync-metrics`})}),_jsxs(_components.td,{children:[`Hourly, only while `,_jsx(_components.strong,{children:`Collect analytics`}),` is on`]}),_jsx(_components.td,{children:`Reads follower and post figures from the networks.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`publishing:recycle-evergreen`})}),_jsx(_components.td,{children:`Hourly, at 20 minutes past`}),_jsx(_components.td,{children:`Lines up the next repeat of every evergreen post that is due one.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`publishing:check-channels`})}),_jsx(_components.td,{children:`Hourly, at 30 minutes past`}),_jsx(_components.td,{children:`Checks channels that have posts due in the next two days, so a revoked token is found before a post fails.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`whatsapp:close-abandoned`})}),_jsx(_components.td,{children:`Hourly`}),_jsx(_components.td,{children:`Ends WhatsApp linking sessions that nobody finished.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`credits:release-expired-holds`})}),_jsx(_components.td,{children:`Hourly, at 45 minutes past`}),_jsx(_components.td,{children:`Releases credit holds that passed their expiry.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`credits:refresh-allowances`})}),_jsx(_components.td,{children:`Hourly, at 50 minutes past`}),_jsx(_components.td,{children:`Refreshes the monthly allowance of yearly and lifetime plans and ends unlimited credits whose plan has lapsed.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`publishing:prune-notifications`})}),_jsxs(_components.td,{children:[`Daily at 03:15, only while `,_jsx(_components.strong,{children:`Keep read notifications`}),` is not set to `,_jsx(_components.strong,{children:`For good`})]}),_jsx(_components.td,{children:`Deletes read publishing notifications older than the retention you chose. Unread ones are kept.`})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`cron-mode-and-worker-mode`,children:`Cron mode and worker mode`}),`\n`,_jsxs(_components.p,{children:[`Under Admin → Publishing → Settings, the `,_jsx(_components.strong,{children:`Sending`}),` card has a `,_jsx(_components.strong,{children:`Posts are sent by`}),` choice.`]}),`\n`,_jsxs(Tabs,{children:[_jsx(Tab,{title:`The scheduler`,id:`the-scheduler`,children:_jsxs(_components.p,{children:[`The default, for hosts that only offer cron. Every minute, the two `,_jsx(_components.code,{children:`publishing:work`}),` lanes process queued jobs for the number of seconds set in `,_jsx(_components.strong,{children:`Each pass sends for`}),`. The value must be between 10 and 55 seconds, and the default is 45, so a pass ends before the next one begins. Lower it if your host stops long cron jobs.`]})}),_jsxs(Tab,{title:`A queue worker`,id:`a-queue-worker`,children:[_jsxs(_components.p,{children:[`For servers that keep a queue worker running under Supervisor or systemd. The scheduler stops running the `,_jsx(_components.code,{children:`publishing:work`}),` lanes, and you run this command from the folder MagicPost is installed in:`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`php`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` artisan`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` queue:work`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --queue=publishing,default,media`})]}),`\n`]})})}),_jsx(_components.p,{children:`The cron job is still required in this mode, because the scheduler decides which posts are due and queues them.`})]})]}),`\n`,_jsxs(_components.p,{children:[`Both modes use the queue named by `,_jsx(_components.code,{children:`QUEUE_CONNECTION`}),` in `,_jsx(_components.code,{children:`.env`}),`, which defaults to `,_jsx(_components.code,{children:`database`}),`. `,_jsx(_components.strong,{children:`System health`}),` reports the `,_jsx(_components.code,{children:`null`}),` driver as a problem, because it throws jobs away, and the `,_jsx(_components.code,{children:`sync`}),` driver as a warning, because each post would then be sent inside the request that queued it. Set `,_jsx(_components.code,{children:`QUEUE_CONNECTION=database`}),` unless you run another queue backend on purpose.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Hand out at most`}),` on the same page limits how many posts are handed to the queue per minute. Posts due at the same moment beyond that limit go out over the following minutes. See `,_jsx(_components.a,{href:`/admin/publishing-settings`,children:`Publishing settings`}),` for the retry, waiting and upload limits.`]}),`\n`,_jsx(Heading,{level:`2`,id:`check-that-it-works`,children:`Check that it works`}),`\n`,_jsx(_components.p,{children:`Open Admin → Publishing → Settings.`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`The `,_jsx(_components.strong,{children:`Sending`}),` card shows `,_jsx(_components.strong,{children:`Last ran`}),` with the time of the last scheduler run, or `,_jsx(_components.strong,{children:`Has not run yet`}),`.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`System health`}),` shows the `,_jsx(_components.strong,{children:`Cron job`}),` line as passed, with the time of the last run. It fails with “The scheduler has never run” or “The scheduler last ran” when the last run is missing or more than five minutes old.`]}),`\n`,_jsxs(_components.li,{children:[`The `,_jsx(_components.strong,{children:`Queue`}),` line reports jobs that have waited more than ten minutes, and says whether the cause is a missing worker or a slow scheduler.`]}),`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`Check again`}),` after you make a change.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`troubleshooting`,children:`Troubleshooting`}),`\n`,_jsxs(AccordionGroup,{children:[_jsx(Accordion,{title:`Has not run yet`,id:`has-not-run-yet`,children:_jsx(_components.p,{children:`The cron job is missing or its command is wrong. Check the path of the application and of the command-line PHP, and make sure the cron user can read the application folder.`})}),_jsx(Accordion,{title:`The cron job runs but posts stay scheduled`,id:`the-cron-job-runs-but-posts-stay-scheduled`,children:_jsxs(_components.p,{children:[`Open `,_jsx(_components.strong,{children:`System health`}),` and read the `,_jsx(_components.strong,{children:`Queue`}),`, `,_jsx(_components.strong,{children:`Waiting posts`}),` and `,_jsx(_components.strong,{children:`Stalled sends`}),` lines. A channel that is paused, needs reconnecting, or belongs to a network that is switched off holds its due posts for up to the `,_jsx(_components.strong,{children:`Wait for a channel for up to`}),` limit.`]})}),_jsx(Accordion,{title:`The Locks line warns about the cache`,id:`the-locks-line-warns-about-the-cache`,children:_jsxs(_components.p,{children:[`Set `,_jsx(_components.code,{children:`CACHE_STORE=database`}),` or `,_jsx(_components.code,{children:`CACHE_STORE=file`}),` in `,_jsx(_components.code,{children:`.env`}),`. The `,_jsx(_components.code,{children:`array`}),` and `,_jsx(_components.code,{children:`null`}),` stores forget everything between requests, so overlapping scheduler runs cannot be kept apart.`]})})]}),`\n`,_jsxs(_components.p,{children:[`For more, see `,_jsx(_components.a,{href:`/troubleshooting/scheduler-and-queue`,children:`Scheduler and queue problems`}),`.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Cron and queue","description":"The one cron job MagicPost needs, every task it runs, how posts are sent in cron or worker mode, and how to check that it is working.","href":"/installation/cron-and-queue"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"The cron command","slug":"the-cron-command","depth":2,"children":[]},{"title":"Add the cron job","slug":"add-the-cron-job","depth":2,"children":[]},{"title":"What the scheduler runs","slug":"what-the-scheduler-runs","depth":2,"children":[]},{"title":"Cron mode and worker mode","slug":"cron-mode-and-worker-mode","depth":2,"children":[]},{"title":"Check that it works","slug":"check-that-it-works","depth":2,"children":[]},{"title":"Troubleshooting","slug":"troubleshooting","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"magic-post","siteName":"MagicPost","title":"Cron and queue - MagicPost","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-02T20:18:30.638Z","originalFileLocation":"installation/cron-and-queue.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"The one cron job MagicPost needs, every task it runs, how posts are sent in cron or worker mode, and how to check that it is working.\">\u003cmeta data-mint-head name=\"application-name\" content=\"MagicPost\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/magic-post/eZDy7I9w--qzcfSd/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/magic-post/eZDy7I9w--qzcfSd/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/magic-post/eZDy7I9w--qzcfSd/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/magic-post/eZDy7I9w--qzcfSd/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/magic-post/eZDy7I9w--qzcfSd/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/magic-post/eZDy7I9w--qzcfSd/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/magic-post/eZDy7I9w--qzcfSd/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/magic-post/eZDy7I9w--qzcfSd/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/magic-post/eZDy7I9w--qzcfSd/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Cron and queue - MagicPost\">\u003cmeta data-mint-head property=\"og:description\" content=\"The one cron job MagicPost needs, every task it runs, how posts are sent in cron or worker mode, and how to check that it is working.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"MagicPost\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://magic-post.mintlify.app/installation/cron-and-queue\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://magic-post.mintlify.site/_mintlify/api/og/v2?division=Installation+%26+updates\u0026amp;title=Cron+and+queue\u0026amp;description=The+one+cron+job+MagicPost+needs%2C+every+task+it+runs%2C+how+posts+are+sent+in+cron+or+worker+mode%2C+and+how+to+check+that+it+is+working.\u0026amp;theme=2f5ef6e968f996d66fe54c57\u0026amp;signature=a57b7333d91c004d1b225797796dc5838b701743fc046b871c6c0efbf59a2cef\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Cron and queue - MagicPost\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"The one cron job MagicPost needs, every task it runs, how posts are sent in cron or worker mode, and how to check that it is working.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://magic-post.mintlify.site/_mintlify/api/og/v2?division=Installation+%26+updates\u0026amp;title=Cron+and+queue\u0026amp;description=The+one+cron+job+MagicPost+needs%2C+every+task+it+runs%2C+how+posts+are+sent+in+cron+or+worker+mode%2C+and+how+to+check+that+it+is+working.\u0026amp;theme=2f5ef6e968f996d66fe54c57\u0026amp;signature=a57b7333d91c004d1b225797796dc5838b701743fc046b871c6c0efbf59a2cef\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/magic-post/eZDy7I9w--qzcfSd/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"MagicPost\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#0353A4\">\u003clink data-mint-head rel=\"canonical\" href=\"https://magic-post.mintlify.app/installation/cron-and-queue\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/installation/cron-and-queue.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://magic-post.mintlify.app/#organization\",\"name\":\"MagicPost\",\"url\":\"https://magic-post.mintlify.app\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/magic-post/wSf-YhNVjpL3AqP0/logo/light.png?fit=max\u0026auto=format\u0026n=wSf-YhNVjpL3AqP0\u0026q=85\u0026s=4c828f56d35df0facd10dc7f9d6d379c\"}},{\"@type\":\"WebSite\",\"@id\":\"https://magic-post.mintlify.app#website\",\"name\":\"MagicPost\",\"url\":\"https://magic-post.mintlify.app\",\"publisher\":{\"@id\":\"https://magic-post.mintlify.app/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://magic-post.mintlify.app/installation/cron-and-queue#webpage\",\"url\":\"https://magic-post.mintlify.app/installation/cron-and-queue\",\"name\":\"Cron and queue\",\"description\":\"The one cron job MagicPost needs, every task it runs, how posts are sent in cron or worker mode, and how to check that it is working.\",\"dateModified\":\"2026-11-02T20:18:30.638Z\",\"isPartOf\":{\"@id\":\"https://magic-post.mintlify.app#website\"},\"breadcrumb\":{\"@id\":\"https://magic-post.mintlify.app/installation/cron-and-queue#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://magic-post.mintlify.app/installation/cron-and-queue#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Installation \u0026 updates\",\"item\":\"https://magic-post.mintlify.app/installation/web-installer\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cron and queue\",\"item\":\"https://magic-post.mintlify.app/installation/cron-and-queue\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://magic-post.mintlify.app/installation/cron-and-queue#article\",\"headline\":\"Cron and queue\",\"name\":\"Cron and queue\",\"description\":\"The one cron job MagicPost needs, every task it runs, how posts are sent in cron or worker mode, and how to check that it is working.\",\"url\":\"https://magic-post.mintlify.app/installation/cron-and-queue\",\"mainEntityOfPage\":{\"@id\":\"https://magic-post.mintlify.app/installation/cron-and-queue#webpage\"},\"dateModified\":\"2026-11-02T20:18:30.638Z\",\"publisher\":{\"@id\":\"https://magic-post.mintlify.app/#organization\"},\"isPartOf\":{\"@id\":\"https://magic-post.mintlify.app#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"MagicPost\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"MagicPost\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/installation/cron-and-queue.md","siteName":"MagicPost","nav":{"global":{"anchors":[{"anchor":"Buy MagicPost","icon":"box-open","href":"https://berkine.dev/scripts/magicpost"},{"anchor":"Support Tickets","icon":"square-info","href":"https://support.berkine.dev/"}]},"groups":[{"group":"Getting started","pages":[{"title":"Introduction","href":"/getting-started/introduction"},{"title":"Requirements","href":"/getting-started/requirements"},{"title":"Quickstart","href":"/getting-started/quickstart"}]},{"group":"Installation \u0026 updates","pages":[{"title":"Web installer","href":"/installation/web-installer"},{"title":"Manual and .env setup","href":"/installation/manual-setup"},{"title":"Post-install checklist","description":"The tasks to finish on the first day, in the order that makes the rest easier.","href":"/installation/post-install-checklist"},{"title":"Cron and queue","href":"/installation/cron-and-queue"},{"title":"Update instructions","description":"Follow update instructions as listed below for each version.","href":"/updates/update-instructions"},{"title":"Changelog","href":"/updates/changelog"},{"title":"License activation","href":"/license/activation"},{"title":"Extended license","href":"/license/extended-license"}]},{"group":"User guide","pages":[{"title":"Dashboard","href":"/user-guide/dashboard"},{"title":"Connect channels","href":"/user-guide/connect-channels"},{"title":"Composer","href":"/user-guide/composer"},{"title":"AI writing and media","href":"/user-guide/ai-tools"},{"title":"Scheduling","href":"/user-guide/scheduling"},{"title":"Calendar","href":"/user-guide/calendar"},{"title":"Posts and statuses","href":"/user-guide/posts-and-statuses"},{"title":"Approval workflow","href":"/user-guide/approvals"},{"title":"Media library","href":"/user-guide/media-library"},{"title":"Saved captions and brand voice","href":"/user-guide/captions-and-brand-voice"},{"title":"RSS feeds and CSV import","href":"/user-guide/feeds-and-import"},{"title":"Analytics","href":"/user-guide/analytics"},{"group":"Account","pages":[{"title":"Profile and security","href":"/account/profile-and-security"},{"title":"Notifications","href":"/account/notifications"},{"title":"Teams","href":"/account/teams"},{"title":"Support tickets","href":"/account/support"},{"title":"Credits","href":"/account/credits"},{"title":"Billing and subscription","href":"/account/billing"},{"title":"Referrals","href":"/account/referrals"},{"title":"API keys","href":"/account/api-keys"},{"title":"REST API","href":"/account/rest-api"},{"title":"Webhooks","href":"/account/webhooks"},{"title":"Language and theme","href":"/account/language-and-theme"}]}]},{"group":"Publishing channels","pages":[{"title":"Publishing channels","href":"/channels/overview"},{"title":"X (Twitter)","href":"/channels/x"},{"title":"LinkedIn","href":"/channels/linkedin"},{"title":"TikTok","href":"/channels/tiktok"},{"title":"YouTube","href":"/channels/youtube"},{"title":"Pinterest","href":"/channels/pinterest"},{"group":"Meta","pages":[{"title":"Facebook Pages","sidebarTitle":"Facebook Pages","href":"/channels/meta/facebook"},{"title":"Instagram","sidebarTitle":"Instagram","href":"/channels/meta/instagram"},{"title":"Threads","sidebarTitle":"Threads","href":"/channels/meta/threads"}]},{"group":"WhatsApp","pages":[{"title":"WhatsApp channels","sidebarTitle":"Overview","href":"/channels/whatsapp/overview"},{"title":"WAHA (self-hosted)","sidebarTitle":"WAHA","href":"/channels/whatsapp/waha"},{"title":"Whapi.Cloud (hosted)","sidebarTitle":"Whapi.Cloud","href":"/channels/whatsapp/whapi"},{"title":"Official WhatsApp Cloud API","sidebarTitle":"Official Cloud API","href":"/channels/whatsapp/official-cloud-api"}]},{"group":"Telegram","pages":[{"title":"Telegram channels","sidebarTitle":"Overview","href":"/channels/telegram/overview"},{"title":"Set up Telegram","sidebarTitle":"Setup","href":"/channels/telegram/setup"}]}]},{"group":"Admin panel","pages":[{"title":"Admin panel overview","href":"/admin/overview"},{"title":"Admin dashboard","href":"/admin/dashboard"},{"title":"Users","href":"/admin/users"},{"title":"Channel credentials","href":"/admin/publishing-platforms"},{"title":"Publishing settings","href":"/admin/publishing-settings"},{"title":"AI models","href":"/admin/ai-models"},{"title":"General settings","href":"/admin/general-settings"},{"title":"Global settings","href":"/admin/global-settings"},{"title":"Registration and login","href":"/admin/registration-and-login"},{"title":"Email and SMTP","href":"/admin/smtp"},{"title":"Privacy and cookies","href":"/admin/privacy-gdpr"},{"title":"Website content","href":"/admin/website-content"},{"title":"Blog","href":"/admin/blog"},{"title":"Support tickets","href":"/admin/support-tickets"},{"title":"System notifications","href":"/admin/system-notifications"},{"title":"System status","href":"/admin/system-status"},{"title":"Languages and translations","href":"/admin/languages"},{"title":"Plugins and themes","href":"/admin/plugins-and-themes"}]},{"group":"SaaS \u0026 billing","pages":[{"title":"SaaS overview","href":"/saas/overview"},{"title":"Subscription plans","href":"/saas/plans"},{"title":"Free tier","href":"/saas/free-tier"},{"title":"Prepaid plans","href":"/saas/prepaid-plans"},{"title":"Credits and allowances","href":"/saas/credits"},{"title":"Subscriptions","href":"/saas/subscriptions"},{"title":"Orders and transactions","href":"/saas/orders"},{"title":"Finance settings","href":"/saas/finance-settings"},{"title":"Invoices","href":"/saas/invoices"},{"title":"Referral program admin","href":"/saas/affiliates"},{"title":"Finance dashboard","href":"/saas/finance-dashboard"},{"group":"Payment gateways","pages":[{"title":"Payment gateways","href":"/gateways/overview"},{"title":"Stripe","href":"/gateways/stripe"},{"title":"PayPal","href":"/gateways/paypal"},{"title":"Paystack","href":"/gateways/paystack"},{"title":"Razorpay","href":"/gateways/razorpay"},{"title":"Mollie","href":"/gateways/mollie"},{"title":"Flutterwave","href":"/gateways/flutterwave"},{"title":"Paddle","href":"/gateways/paddle"},{"title":"YooKassa","href":"/gateways/yookassa"},{"title":"Braintree","href":"/gateways/braintree"},{"title":"Iyzico","href":"/gateways/iyzico"},{"title":"Midtrans","href":"/gateways/midtrans"},{"title":"Coinbase Commerce","href":"/gateways/coinbase"},{"title":"Bank transfer","href":"/gateways/bank-transfer"},{"title":"Wallet","href":"/gateways/wallet"}]}]},{"group":"Plugins","pages":[{"title":"Plugins overview","href":"/plugins/overview"}]},{"group":"Integrations","pages":[{"title":"Integrations overview","href":"/integrations/overview"},{"title":"OpenAI","href":"/integrations/ai/openai"},{"title":"Anthropic","href":"/integrations/ai/anthropic"},{"title":"Google Gemini","href":"/integrations/ai/gemini"},{"title":"xAI Grok","href":"/integrations/ai/xai"},{"title":"fal.ai","href":"/integrations/ai/fal"},{"title":"Google login","href":"/integrations/login/google"},{"title":"Facebook login","href":"/integrations/login/facebook"},{"title":"X login","href":"/integrations/login/x"},{"title":"LinkedIn login","href":"/integrations/login/linkedin"}]},{"group":"Advanced","pages":[{"title":"Environment variables","href":"/advanced/environment-variables"},{"title":"File storage","href":"/advanced/storage"},{"title":"Video processing","href":"/advanced/video-processing"},{"title":"Cache and optimisation","href":"/advanced/cache"},{"title":"Google Analytics","href":"/advanced/google-analytics"},{"title":"Google reCAPTCHA","href":"/advanced/google-recaptcha"},{"title":"Google Maps","href":"/advanced/google-maps"}]},{"group":"Troubleshooting","pages":[{"title":"Installation problems","href":"/troubleshooting/installation"},{"title":"Scheduler and queue problems","href":"/troubleshooting/scheduler-and-queue"},{"title":"Failed posts","href":"/troubleshooting/publishing-errors"},{"title":"Channel connection problems","href":"/troubleshooting/channel-connections"},{"title":"Billing problems","href":"/troubleshooting/billing-and-payments"},{"title":"FAQ","href":"/troubleshooting/faq"}]}]},"basePath":"","title":"Cron and queue - MagicPost","buildId":"dpl_DqYu5MPb49gWBBbUGgpHQUmCHY3P","deploymentId":"dpl_DqYu5MPb49gWBBbUGgpHQUmCHY3P","dynamics":["07c022d89b","a74be98ba7"],"chunks":["Frame-u3J1-UOn.js","DynamicMarkdown-B-f2cqXQ.js","zoom-image-lightbox-DTFzvaXJ.js","lightbox-handle-r17bVUz3.js"]}