ImpulseCore
The Core cron runner
One Core cron entry dispatches every module’s registered tasks. Predictable cadence, heartbeats per task, no per-module crontab clutter.
1. The single Core cron line
Section titled “1. The single Core cron line”# ImpulseCore — cron runner (every 5 minutes)*/5 * * * * /usr/bin/php /path/to/whmcs/modules/addons/impulsecore/cron/runner.phpThat’s it. Whether you have one Impulse module installed or five, this is the only cron line you need from Core. Use your PHP 8.x CLI binary (Plesk: /opt/plesk/php/8.3/bin/php; cPanel: /opt/cpanel/ea-php83/root/usr/bin/php; generic LAMP: usually /usr/bin/php) and run it as the user that owns the WHMCS files. The runner only runs from the command line — it refuses web requests.
Each tick, the runner walks mod_impulsecore_cron_tasks and runs every enabled task whose next_run_at is in the past. Every run is recorded in mod_impulsecore_cron_log (status, duration, result or error) and stamps the task’s last_run_at, so Operations → Cron can show which tasks are healthy and which are stuck. Each task runs one at a time: a run still going when the next tick arrives is skipped, not doubled.
Core also runs its due tasks whenever WHMCS’s own cron fires, so scheduled work still happens if the dedicated line is missing — just less predictably. The dedicated line is the recommended setup.
2. How tasks register
Section titled “2. How tasks register”Modules declare their tasks in their manifest:
"cron_tasks": [ {"name": "provision", "cadence": "2min"}, {"name": "usage_sync", "cadence": "hourly"}, {"name": "domain_polling", "cadence": "15min"}]Each declared task is backed by a handler class in the module’s lib/Cron/ directory. When the module is activated (or upgraded), Core inserts or updates its rows in mod_impulsecore_cron_tasks; a new task is enabled and due straight away, so it runs on the next tick. Re-activating or upgrading the module is idempotent — existing rows are updated rather than duplicated, and a task’s enabled/disabled state is never changed by an upgrade.
3. Crons Core ships itself
Section titled “3. Crons Core ships itself”Core registers its own tasks the same way modules do. After Core activates, you’ll see these in Operations → Cron:
| Task | Cadence | Purpose |
|---|---|---|
license_refresh | daily | Re-verify cached license keys against the licensing server and advance grace windows. |
audit_purge | daily | 90-day retention on mod_impulsecore_audit_log; also trims the cron run log (successful runs after 14 days, failures after 90). |
module_reconcile | daily | Clean up registry rows and leftover cron/hook rows for modules whose files were removed. |
admin_proxy_health_check | 15 min | Ping every module server’s health endpoint (its admin proxy, or the Plesk / WHM API for the hosting modules) and flag servers that go degraded or down. |
lifecycle_warn | daily | Send the final warning before a suspended or terminated service’s data is purged. |
lifecycle_purge | hourly | Purge services whose grace window has ended. |
| Security & Maintenance pipeline | ||
security_collect | daily | Refresh per-service + per-server snapshots from registered Collectors. |
cve_feed_refresh | hourly | Pull Ubuntu USN + CISA KEV. |
nvd_product_feed_refresh | daily | Pull NVD CVEs by CPE for every active module’s cve_products. |
security_apply_critical | hourly | Match snapshots × CVE feed; schedule critical / KEV patches and high-severity patches. |
security_apply_window | 5 min | Run due maintenance schedules, honouring each customer’s maintenance window. |
maintenance_warn | daily | Send the 24h-ahead maintenance notice. |
security_freshness_check | daily | Raise alerts for stale snapshots, collector errors, failed patches and stale feeds; schedule reboots for hosts that need one. |
security_snapshot_expiry | daily | Delete held pre-patch snapshots 7 days after they were taken. |
security_events_purge | daily | 90-day retention on mod_impulsecore_security_events. |
upstream_release_refresh | daily | Check for new upstream releases of the products modules run. |
| Projects and monitoring | ||
project_reconcile, project_idle_check, project_orphan_scan | 2 min / daily / daily | Keep project components in step, pause idle projects, flag orphaned components for review. |
status_aggregate | 5 min | Poll each active module’s health endpoint and cache the result. |
metrics_collect, fleet_probe, node_alert_evaluate, alert_evaluate, monitoring_forward, metrics_export_otlp | 5 min | Collect metrics, probe servers, evaluate alert rules and forward alerts to your destinations. |
synthetic_probe | 15 min | Run synthetic checks. |
metrics_purge | daily | Metrics retention. |
A few more tasks serve optional integrations or one-off upgrade work (such as provider_log_redaction, which finishes a credential clean-up of WHMCS’s module log after an upgrade); they report skipped or finish instantly when there is nothing to do.
4. Force a task to run right now
Section titled “4. Force a task to run right now”Stamp next_run_at = NOW() on the task row and the runner will pick it up on the next tick (within 5 min):
UPDATE mod_impulsecore_cron_tasksSET next_run_at = NOW()WHERE name = 'security_collect';To tick immediately instead of waiting, run the runner by hand as the cron user — it runs every due task and prints a one-line summary:
/usr/bin/php /path/to/whmcs/modules/addons/impulsecore/cron/runner.phpA task’s own output — its result or the error it failed with — is in Operations → Cron → Recent runs. Useful when you’ve just changed something a daily task depends on (added a new server, registered a new module’s CPE) and don’t want to wait 24 hours for the next tick.
5. Diagnosing missed runs
Section titled “5. Diagnosing missed runs”Operations → Cron lists every registered task with its last and next run and a status: healthy (last run within twice its effective interval), overdue (past twice), stale (past six times), plus due, scheduled and disabled. The effective interval is the task’s cadence or the runner’s tick, whichever is longer. The Automation & Setup panel shows when the runner last ticked: “Cron is running”, “ticking but slower than recommended” (no tick for over 10 minutes) or “Cron is stale” (none for over 30 minutes).
If every task is stale, the cron line isn’t firing — verify with:
SELECT MAX(started_at) FROM mod_impulsecore_cron_log;-- Should be within the last 5 minutes if cron is healthy.If the timestamp is missing or stale, debug at the system-cron level:
- Confirm the crontab line exists:
crontab -l | grep impulsecore - Confirm the cron user can read the WHMCS files, including
configuration.php— the runner loads WHMCS before it runs anything. - Run the cron script by hand from the same user: any error message will land on stdout.
- Check the system mail for cron output:
tail /var/spool/mail/rootorjournalctl -u cron.
6. When modules need their own cron line
Section titled “6. When modules need their own cron line”They don’t. Every current Impulse module registers its background work — provisioning polls, usage syncs, alerting, upgrades — with Core’s runner, and none ships a crontab line of its own. Several modules register 2-minute tasks for in-flight server provisioning, and ImpulseNotify’s queue and inbound tasks run every minute; they run on each tick of Core’s line, so tick every minute if you want them to keep their 2-minute pace.
The Security & Maintenance pipeline also rides on Core’s runner — modules don’t need to add anything for it to work.