🔎 Isolate the bug
✍️ Describe the bug
Even with add_filter( 'action_scheduler_use_async_request_runner', '__return_false', PHP_INT_MAX ) applied in a must-use plugin, Meta for WooCommerce continues dispatching async HTTP loopback requests to admin-ajax.php?action=as_async_request_queue_runner. The filter is confirmed loading correctly via wp plugin list --type=mustuse.
This caused 35+ concurrent MySQL connections all executing the same slow query simultaneously, driving server load average to 40+ on an 8-core server and making the site unresponsive.
The plugin also generates extremely high Action Scheduler volume — approximately 200,000+ rows per day — primarily from facebook_for_woocommerce_5_minute_heartbeat firing every 5 minutes and hourly promotions feed regeneration chains (chain_start, chain_batch, chain_end).
🚶♀️ Steps to reproduce
- Install Meta for WooCommerce 3.5.18 on a WooCommerce store with server-side cron (DISABLE_WP_CRON = true)
- Add add_filter( 'action_scheduler_use_async_request_runner', '__return_false', PHP_INT_MAX ) to a must-use plugin
- Monitor Nginx access logs for admin-ajax.php?action=as_async_request_queue_runner
- Monitor MySQL processlist for concurrent SELECT COUNT(DISTINCT claim_id) FROM wp_actionscheduler_actions queries
- Observe that async runner requests continue despite the filter, and concurrent MySQL queries pile up
✔️ Expected behavior
add_filter( 'action_scheduler_use_async_request_runner', '__return_false' ) returning false should completely prevent Meta for WooCommerce from dispatching async loopback requests to the queue runner endpoint. When DISABLE_WP_CRON is true and a server cron is in use, no async HTTP requests should be dispatched.
Additionally, the volume of Action Scheduler rows generated (~200K rows/day on a store with 29 products) seems disproportionate and worth reviewing, particularly the 5-minute heartbeat which alone generates ~288 rows/day.
Workaround required: Had to explicitly intercept the AJAX endpoint in a must-use plugin to prevent MySQL overload:
`add_action( 'wp_ajax_nopriv_as_async_request_queue_runner', function() {
wp_die( '', '', [ 'response' => 403 ] );
}, 0 );
add_action( 'wp_ajax_as_async_request_queue_runner', function() {
wp_die( '', '', [ 'response' => 403 ] );
}, 0 );
🗃 Logs
Details
Environment:
- Meta for WooCommerce: 3.5.18 (latest)
- WooCommerce: 10.5.2
- WordPress: 6.9.1
- PHP: 8.3.30
- MySQL: 8.4.8
- Server: AlmaLinux, cPanel/WHM, 8 CPU cores
MySQL processlist showing 35+ concurrent stuck queries (load average 40.20):
| xyz_db2 | Query | 73 | executing | SELECT COUNT(DISTINCT claim_id) FROM wp_actionscheduler_actions WHERE claim_id != 0 AND status IN ( 'pending', 'in-progress') |
| xyz_db2 | Query | 72 | executing | SELECT COUNT(DISTINCT claim_id) FROM wp_actionscheduler_actions WHERE claim_id != 0 AND status IN ( 'pending', 'in-progress') |
| xyz_db2 | Query | 69 | executing | SELECT COUNT(DISTINCT claim_id) FROM wp_actionscheduler_actions WHERE claim_id != 0 AND status IN ( 'pending', 'in-progress') |
-- (35+ identical rows)
Nginx access log showing async runner requests continuing despite filter:
[01/Mar/2026] "POST /wp-admin/admin-ajax.php?action=as_async_request_queue_runner&nonce=xxx HTTP/1.1" 200
-- (90,672 requests from server's own IP in a single log file)
Action Scheduler table volume (primarily from this plugin):
complete | 801,804 (all within 30 days, majority within 2 days)
pending | 206
Top hooks by volume:
facebook_for_woocommerce_5_minute_heartbeat -- every 5 minutes
facebook_for_woocommerce_hourly_heartbeat -- every hour
wc_facebook_regenerate_feed_promotions -- every hour + spawns chain jobs
facebook_for_woocommerce/jobs/promotions_feed_generator/chain_start
facebook_for_woocommerce/jobs/promotions_feed_generator/chain_batch
facebook_for_woocommerce/jobs/promotions_feed_generator/chain_end
🔎 Isolate the bug
✍️ Describe the bug
Even with
add_filter( 'action_scheduler_use_async_request_runner', '__return_false', PHP_INT_MAX )applied in a must-use plugin, Meta for WooCommerce continues dispatching async HTTP loopback requests toadmin-ajax.php?action=as_async_request_queue_runner. The filter is confirmed loading correctly viawp plugin list --type=mustuse.This caused 35+ concurrent MySQL connections all executing the same slow query simultaneously, driving server load average to 40+ on an 8-core server and making the site unresponsive.
The plugin also generates extremely high Action Scheduler volume — approximately 200,000+ rows per day — primarily from
facebook_for_woocommerce_5_minute_heartbeatfiring every 5 minutes and hourly promotions feed regeneration chains (chain_start, chain_batch, chain_end).🚶♀️ Steps to reproduce
✔️ Expected behavior
add_filter( 'action_scheduler_use_async_request_runner', '__return_false' )returning false should completely prevent Meta for WooCommerce from dispatching async loopback requests to the queue runner endpoint. When DISABLE_WP_CRON is true and a server cron is in use, no async HTTP requests should be dispatched.Additionally, the volume of Action Scheduler rows generated (~200K rows/day on a store with 29 products) seems disproportionate and worth reviewing, particularly the 5-minute heartbeat which alone generates ~288 rows/day.
Workaround required: Had to explicitly intercept the AJAX endpoint in a must-use plugin to prevent MySQL overload:
🗃 Logs
Details
Environment:
MySQL processlist showing 35+ concurrent stuck queries (load average 40.20):
Nginx access log showing async runner requests continuing despite filter:
Action Scheduler table volume (primarily from this plugin):
Top hooks by volume: