CLI tool
humanmade/Cavalcade avatar
humanmade/Cavalcade

Cavalcade replaces WordPress pseudo-cron with a queue and a worker pool

A better wp-cron. Horizontally scalable, works perfectly with multisite.

542 stars49 forksPHPNOASSERTION

At a glance

What is it?
Cavalcade is a Human Made WordPress plugin that keeps the existing wp-cron calls working while moving the scheduled work into a database table and a separate runner daemon that spawns workers through WP-CLI. It is built for multisite and for high traffic sites, it is licensed GPLv2 or later, and the newest release is 2.0.3 from February 2026.
Who is it for?
Adopt Cavalcade if you run WordPress at a scale where wp-cron is dropping work, especially on multisite, and you have the ability to run a long-lived runner process alongside PHP. Do not adopt it for a small site, because a daemon and a worker pool is real infrastructure for a problem you probably do not have yet.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 136 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A drop-in replacement, and nothing on the WordPress side changes

Cavalcade is a scalable job system, designed as a drop-in replacement for WordPress's built-in pseudo-cron system.

That first sentence is the whole pitch. The problem with wp-cron is that it is not a scheduler. It is a hook that runs when a page is loaded, so on a quiet site a scheduled task does not run at the scheduled time, and on a busy site the same task can be triggered by several requests at once. The usual fixes are to disable it and use a real system cron, or to accept the flakiness.

Cavalcade's approach is to keep the API and change the plumbing. From the WordPress side, none of your code needs to change. Cavalcade transparently integrates with the existing wp-cron functions to act as a full replacement, and it pushes those jobs off into their own database table for efficient storage.

So the calling code stays exactly as it is, the jobs stop being tied to page views, and the scheduling moves somewhere you control. For a site where the existing schedule calls are already in place, that is a much smaller change than rewriting every call site against a queue library.

The repository is a WordPress plugin rather than a library, with plugin.php at the root, an inc directory for the implementation, a composer.json, a phpunit.xml.dist, a phpcs.ruleset.xml for coding standards, a tests directory and a docs directory. The topics list wp-cron, scheduled-tasks, workers, multisite, wordpress-plugin and wp-cli, which is the vocabulary of the whole design.

The runner daemon and the workers it spawns

At the core of Cavalcade is the job runner. The runner is a daemon that supervises the entire system. It constantly checks the database for new jobs, and it is responsible for spawning and managing workers to handle the jobs when they are ready.

Then the runner spawns workers, which perform the actual tasks themselves, and that is done by running a special WP-CLI command.

The two-level split is the important design point. The runner is a supervisor: it watches the queue and it manages the pool of workers. The workers are the processes that actually run a WordPress callback. Separating the two means the runner does not need to be in a request context, and a worker can be killed and replaced without the supervisor losing its place.

Using WP-CLI for the worker is a deliberate choice, and it has practical consequences. WP-CLI already knows how to bootstrap WordPress, load the active theme and plugins, and run in a given site context, so the worker does not have to reimplement any of that. In a multisite network, where a single installation serves thousands of sites, that bootstrap is the part you do not want to get subtly wrong, and inheriting the supported path is worth more than the small overhead of a process start.

The docs directory has a plugins page, described as covering extending the functionality of Cavalcade, which is where the extension points for the queue and the runner behaviour would be documented.

Multisite and horizontal scale are the design constraints

The tagline is a better wp-cron, horizontally scalable, works perfectly with multisite, and both of those qualifications are load bearing.

On multisite, the problem is different from a single site. A network of thousands of sites has a shared database, and the wp-cron trigger is fired per site, so a scheduled task on a quiet site in the network waits for a visitor who may never come. Moving the trigger out of the page view and into a runner that polls the shared table fixes that for every site in the network at once, and that is the shape of the problem Cavalcade was written for.

On horizontal scale, the design consequence is that jobs are rows in a database table rather than work attached to a request. A runner can be started on more than one machine, and the workers can be spread out, because the queue is the shared state rather than the process.

The people behind it say who the target is. Cavalcade was created by Human Made for high volume and large-scale sites, and the readme says they run it on sites with millions of monthly page views, and thousands of sites, naming Happytables, The Tab and the United Influencers network.

That context matters for a reader deciding whether to use it. This is infrastructure for a scale where a page-load-triggered cron has become a real reliability problem, not a general improvement to WordPress scheduling.

A database table instead of a request hook

The storage choice is the second half of the drop-in design. Cavalcade pushes the jobs off into their own database table for efficient storage.

The efficiency argument is about the query, not the row count. A scheduled task in WordPress is stored as an option row, one per event, and the pseudo-cron queries all of them on every page load to find out what is due. Moving to a dedicated table means the runner can ask a narrow question, something like which jobs are due now, against an index, and get a small answer.

That is also what makes the two-level architecture possible. A table is a queue that more than one process can read. An option row is not.

The plugin structure follows. There is a plugin.php at the root, which is where the WordPress integration lives, and an inc directory with the rest, and a composer.json for the PHP dependencies. A composer.json in a WordPress plugin usually means the plugin is a Composer package first and a plugin second, which is consistent with a project that expects to be developed with modern PHP tooling while still shipping as a drop-in plugin directory.

The tests directory and the phpunit.xml.dist show there is a test suite, and the .travis.yml with a build status badge and the codecov badge in the header show it was wired into Travis CI at some point, with coverage tracked through codecov.

The documentation, and the questions it is meant to answer

The documentation lives in the docs directory of the repository, and the readme lists four documents with an explanation of what each is for.

The first is Motivation, titled Why Cavalcade, which is the place the pseudo-cron problem is argued out. The second is Installation. The third is Example Use Cases. The fourth is Plugins, which covers extending the functionality of Cavalcade.

Those four documents map to the four decisions a reader has to make. Whether the problem is real for you, how to get it running, what you would use it for, and what you would need to build on top of it.

The homepage is a project page on Human Made's engineering site, at engineering.hmn.md/projects/cavalcade, so there is a longer write-up outside the repository as well.

Two details about the project's shape are worth recording. The maintainer is Ryan McCue, and the readme is explicit that the project is a Human Made project. The plugin ships with a GPLv2 or later licence in a LICENSE.txt file, which is the standard choice for a WordPress plugin, and the repository is not archived.

Maintenance, and what the version history suggests

The release history is sparse in an informative way. The tags are 2.0.3 from 2026-02-03, 2.0.2 from 2020-12-03 and 2.0.1 from 2020-07-31.

So there is a cluster of releases in the middle of 2020, and then a long gap, and then a single release in February 2026. The last push was on 2026-06-09.

That pattern reads like a project that reached a stable design, went quiet because the design was adequate for the sites it was built for, and then had a release when something needed fixing. It is a good sign that the repository is not archived and that a new version appeared, but it is a signal that this is not software with an active release cadence.

For a piece of infrastructure that runs in the background of a site, that is less alarming than it would be for a library. The interesting failure modes are operational, and the runner daemon and the worker command are the parts that would need attention if the site environment changed underneath them.

The practical note is that the version you install is 2.0.3, and the documentation in the repository is the documentation for that version, so if you are following an older installation guide elsewhere you should check it against the current docs directory.

The wp-cli topic on the repository and the special WP-CLI command that runs the workers are the two things to get right in a first installation, and both are covered by the installation document.

Editorial conclusion

Adopt Cavalcade if you run WordPress at a scale where wp-cron is dropping work, especially on multisite, and you have the ability to run a long-lived runner process alongside PHP. Do not adopt it for a small site, because a daemon and a worker pool is real infrastructure for a problem you probably do not have yet. Before you install, check three things: that your hosting lets you run a persistent background process, since the runner has to be alive for jobs to be picked up, that you read the installation notes in the docs directory, since the runner needs to be pointed at the right site in a multisite network, and that you understand the change in failure mode, because a job that fails now fails visibly in a worker rather than silently when a page load happens to trigger it.

Frequently asked questions

What does Cavalcade do for WordPress cron?

It acts as a drop-in replacement for the built-in pseudo-cron. The existing wp-cron calls keep working unchanged, and Cavalcade transparently integrates with them while pushing the jobs into their own database table for efficient storage.

How does the Cavalcade job runner work?

The runner is a daemon that supervises the whole system. It constantly checks the database for new jobs and spawns and manages workers to handle them when they are ready, and the workers perform the actual tasks by running a special WP-CLI command.

Is Cavalcade suited to a multisite network?

Yes, that is one of its two stated design goals alongside horizontal scalability. It was created by Human Made for high volume and large-scale sites, and they say they run it on sites with millions of monthly page views across thousands of sites.

What licence does Cavalcade use?

GPLv2 or later, recorded in the LICENSE.txt file in the repository. The releases are 2.0.3 from 2026-02-03, 2.0.2 from 2020-12-03 and 2.0.1 from 2020-07-31, with the last push on 2026-06-09.

Where is the documentation for Cavalcade?

In the docs directory of the repository, with a Motivation page explaining why the project exists, an Installation guide, an Example Use Cases page and a Plugins page on extending the functionality. There is also a longer project page on the Human Made engineering site.

Official sources

  1. humanmade/Cavalcade on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/humanmade-cavalcade.svg)](https://hysenlabs.com/projects/humanmade-cavalcade)

Was this useful?