Cron vs Joomla Lazy Scheduler and WebCron

As a Joomla developer, I often leave local dev site tabs open in the background for hours, sometimes days. Recently, I switched back to one of these tabs for a quick check, with the DevTools Network panel open. To my horror, dozens, maybe over a hundred AJAX calls fired at once, flooding the network log. The browser froze, navigation stalled, and it took agonizing seconds to recover. “That’s why it’s so slow sometimes!” I realized, pinpointing Joomla’s Lazy Scheduler as the culprit, piling up tasks in the background. This frustrating experience reminded me of the tried and true solution: regular cron with Joomla’s scheduler:run CLI command.

The Unreliability of Lazy Scheduler and WebCron

Joomla’s com_scheduler component automates tasks like cache clearing and email sending, but its two trigger methods: Lazy Scheduler and WebCron, part of the plg_system_schedulerunner plugin - are unreliable.

Before someone accuses me of misrepresenting the Schedule Runner plugin as being "unreliable" - that's not what I mean.  The plugin works just fine - as intended.  I mean, it doesn't run scheduled tasks on a reliable schedule.  Tasks are triggered after they're due - by the next website visitor.  What happens if your next visitor doesn't arrive until hours later?  The tasks run hours late.

Lazy Scheduler: Visitor-Driven Instability

Lazy Scheduler uses client-side JavaScript (run-schedule.js) to trigger tasks via AJAX calls on qualifying page loads (when lazy_scheduler.enabled is true and tasks are due):

index.php?option=com_ajax&plugin=RunSchedulerLazy&group=system&format=raw


Drawbacks:

  1. Traffic Dependency: Tasks require visitor page loads. On low-traffic sites (like my local dev sites) tasks may not run for hours or days, delaying operations like backups.
  2. Browser Lockup: Browsers throttle setInterval in background tabs, queuing AJAX calls. When the tab regains focus, as I saw in DevTools, queued calls fire simultaneously, freezing the browser and disrupting navigation.
  3. Performance Impact: Resource-heavy tasks strain servers, slowing page loads for users unaware their browsers are triggering maintenance.

WebCron: External but Still Flawed

WebCron allows external services (e.g., cron monitoring tools) to trigger tasks via a secure URL:

index.php?option=com_ajax&plugin=RunSchedulerWebcron&group=system&format=json&hash=...

Drawbacks:

  1. External Dependency: WebCron relies on external services, which may fail or be misconfigured, risking missed tasks.
  2. Concurrency Limitations: Joomla’s Scheduler runs one task at a time by default. A hung task (e.g., due to timeout or failed status update) blocks the queue, halting others. A concurrency flag exists but isn’t exposed in the UI, limiting flexibility.
  3. Security Complexity: Managing secure hashes adds setup complexity and risks if exposed.

Both methods are less reliable than server-side cron, with Lazy Scheduler’s traffic dependency and browser issues, and WebCron’s external risks and concurrency bottlenecks.

The Tried and True Solution: scheduler:run with Cron

No Conan, not CROM - CRON!
No Conan, not CROM - CRON!

Joomla’s scheduler:run CLI command, executed via regular server-side cron jobs, runs tasks without relying on browsers or external services, avoiding the issues I encountered. Benefits include:

  1. Traffic-Independent: Cron jobs (e.g., */15 * * * * php /path/to/joomla/cli/joomla.php scheduler:run) ensure tasks run on schedule, even on low-traffic sites.
  2. No Browser Issues: Server-side execution eliminates setInterval pile-up, preventing browser lockup like I observed.
  3. Robust Concurrency: CLI jobs run in the CliApplication environment, allowing multiple instances via cron without the Scheduler’s single-task lock, avoiding blocks from hung tasks.
  4. Predictable Scheduling: Admins can set precise intervals or run specific tasks (scheduler:run --id=123), optimizing for low-traffic periods.
  5. Seamless Integration: Uses the same Scheduler class, requiring no task changes.
  6. Enhanced Security: No client-side hashes or external dependencies.

Switching to Cron

  1. Disable Client-Side Triggers: In Joomla’s admin panel, go to System > Manage > Plugins, find plg_system_schedulerunner (search for "System - Schedule Runner"), set lazy_scheduler.enabled and webcron.enabled to 0.
  2. Set Up Cron:
    • Test: php /path/to/joomla/cli/joomla.php scheduler:run
    • Add cron job (via crontab -e or cPanel):
      */15 * * * * php /path/to/joomla/cli/joomla.php scheduler:run >> /path/to/joomla/logs/scheduler.log 2>&1
  3. Monitor: Check scheduler.log for task outcomes.

Practical Considerations

  • User Experience: Lazy Scheduler burdens visitors’ browsers, risking freezes like I saw. WebCron’s external triggers still introduce risks. Cron runs server-side, ensuring smooth navigation.
  • Reliability: Cron’s predictable execution and concurrency flexibility avoid WebCron’s external risks and Lazy Scheduler’s fragility, as seen in my DevTools flood.
  • Setup Trade-Offs: Lazy Scheduler and WebCron are accessible for shared hosting but unreliable. Cron requires server setup, but tools like cPanel make it manageable for non-technical users.

Conclusion

Setting up a scheduler cron job is one of the first things I do on production sites. Skipping that configuration on my dev site reminded me of just how important that step is for performance and user-experience. Something so simple, so easy to overcome, is probably causing noticeable performance issues on many Joomla sites. I don't see many people adding it to their Joomla how-to's.

My dev site’s freeze, exposed by a flood of AJAX calls in DevTools, revealed Lazy Scheduler’s unreliability. WebCron, while externally triggered, shares concurrency and dependency issues. The tried and true solution - Joomla’s scheduler:run CLI command with regular cron is: traffic-independent, browser-free, and reliable, with robust concurrency handling. Switch to cron for seamless automation and a better user experience.