Running Action Scheduler at Scale (WP-CLI)

This guide documents the scale-focused knobs exposed by Action Scheduler’s WP-CLI commands and queue runner. All behavior described here is verified in the classes/WP_CLI/ implementation and related runner classes.

Goal

Run Action Scheduler in high-throughput environments using wp action-scheduler run, with explicit control over batching, concurrency, and memory pressure.

Disabling the Async Request Runner

Action Scheduler can dispatch async requests to process actions via ActionScheduler_AsyncRequest_QueueRunner. To run exclusively via system cron + WP-CLI, disable the async request runner.

Two code-level mechanisms are supported by core:

  1. Disable the async request runner via filter

ActionScheduler_AsyncRequest_QueueRunner::allow() applies the action_scheduler_allow_async_request_runner filter. Returning false prevents async dispatch.

add_filter( 'action_scheduler_allow_async_request_runner', '__return_false' );
  1. Disable the default action_scheduler_run_queue hook

The queue runner attaches to the action_scheduler_run_queue hook during initialization. Removing this action disables the default runner. The system status command reports “(disabled)” when the hook is not attached.

remove_action( 'action_scheduler_run_queue', array( ActionScheduler::runner(), 'run' ) );

Tip: wp action-scheduler status will display whether the runner is disabled.

Running via System Cron

Schedule WP-CLI runs through your system cron to process jobs without WP-Cron or async requests.

Example cron entry (every minute)

* * * * * cd /path/to/wordpress && wp action-scheduler run --batch-size=200 --batches=1 --allow-root

CLI syntax

wp action-scheduler run [--batch-size=<size>] [--batches=<size>] [--cleanup-batch-size=<size>] [--hooks=<hooks>] [--group=<group>] [--exclude-groups=<groups>] [--free-memory-on=<count>] [--pause=<seconds>] [--force]

Concurrent Runners

Action Scheduler enforces a maximum number of concurrent batches per store. The queue runner checks this via ActionScheduler_Abstract_QueueRunner::has_maximum_concurrent_batches().

Allow more concurrent batches

Use the action_scheduler_queue_runner_concurrent_batches filter to raise the limit:

add_filter( 'action_scheduler_queue_runner_concurrent_batches', static function () {
	return 5;
} );

Override concurrency checks per run

WP-CLI can override the concurrency check using --force:

wp action-scheduler run --force

Note: --force bypasses the “too many concurrent batches” error in the WP-CLI queue runner.

Performance Tuning with WP-CLI

Batch size and cleanup size

  • --batch-size=<size>: Max actions to run per batch (default 100).
  • --cleanup-batch-size=<size>: Max actions to clean per batch (default --batch-size).

Freeing memory and pauses

wp action-scheduler run exposes two memory controls that delegate to ActionScheduler_DataController:

  • --free-memory-on=<count>: Free memory every N actions (default 50, 0 disables).
  • --pause=<seconds>: Seconds to sleep when freeing memory (default 0).

Scoping work by hook or group

  • --hooks=<hooks>: Comma-separated list of hooks to run (no spaces).
  • --group=<group>: Only run actions in a specific group.
  • --exclude-groups=<groups>: Comma-separated list of groups to exclude (ignored if --group is set).

Examples

# Process only a specific hook
wp action-scheduler run --hooks=wc_update_product_lookup_tables

# Process only one group in larger batches
wp action-scheduler run --group=action-scheduler --batch-size=500

# Exclude a noisy group
wp action-scheduler run --exclude-groups=importer

Cleaning at Scale

Large installations should periodically clean old actions to keep tables lean.

wp action-scheduler clean --status=complete,failed,canceled --before='30 days ago'

CLI syntax

wp action-scheduler clean [--batch-size=<size>] [--batches=<size>] [--status=<status>] [--before=<datestring>] [--pause=<seconds>]