Deferred Mode Implementation
Overview
Section titled “Overview”Deferred mode allows the REST API endpoint to respond immediately (HTTP 202 Accepted) while processing cron jobs in the background. This prevents timeout issues on large networks and improves integration with external systems.
Add the defer=1 parameter to any REST API call:
# JSON mode with defercurl https://example.com/wp-json/all-sites-cron/v1/run?defer=1
# GitHub Actions mode with defercurl https://example.com/wp-json/all-sites-cron/v1/run?ga=1&defer=1How It Works
Section titled “How It Works”1. Request Flow
Section titled “1. Request Flow”Client Request → REST Handler → Immediate Response (HTTP 202) ↓ Background Processing ↓ Cron Jobs Execute ↓ Log Results2. Connection Closure Methods
Section titled “2. Connection Closure Methods”The plugin uses different methods based on webserver configuration:
FastCGI Method (Preferred)
Section titled “FastCGI Method (Preferred)”if ( function_exists( 'fastcgi_finish_request' ) ) { // Send response echo wp_json_encode( $response->get_data() );
// Close connection fastcgi_finish_request();
// Continue processing in background ( new \Soderlind\Multisite\AllSitesCron\Cron_Runner() )->run_all_sites();}Supported Environments:
- Nginx + PHP-FPM ✅
- Apache + mod_fcgid ✅
- Litespeed ✅
Fallback Method
Section titled “Fallback Method”// Flush output buffersob_start();echo wp_json_encode( $response->get_data() );header('Connection: close');header('Content-Length: ' . ob_get_length());ob_end_flush();flush();
// Continue processing( new \Soderlind\Multisite\AllSitesCron\Cron_Runner() )->run_all_sites();Supported Environments:
- Apache + mod_php ⚠️ (works but less reliable)
- Most shared hosting ⚠️ (depends on configuration)
Webserver Compatibility
Section titled “Webserver Compatibility”✅ Full Support
Section titled “✅ Full Support”| Environment | Method | Notes |
|---|---|---|
| Nginx + PHP-FPM | FastCGI | Best performance, cleanest connection closure |
| Apache + mod_fcgid | FastCGI | Excellent performance |
| Litespeed | FastCGI | Full support with Litespeed API |
⚠️ Partial Support
Section titled “⚠️ Partial Support”| Environment | Method | Notes |
|---|---|---|
| Apache + mod_php | Fallback | Works but connection may not close immediately |
| Shared Hosting | Fallback | Depends on hosting provider’s PHP configuration |
❌ Not Recommended
Section titled “❌ Not Recommended”| Environment | Issue |
|---|---|
| CGI mode | Cannot close connection early |
| Hosting with aggressive timeouts | May kill long-running processes |
Testing Your Environment
Section titled “Testing Your Environment”1. Check for FastCGI Support
Section titled “1. Check for FastCGI Support”php -r "echo function_exists('fastcgi_finish_request') ? 'FastCGI: YES' : 'FastCGI: NO';"2. Test Deferred Mode
Section titled “2. Test Deferred Mode”# Time the request (should return immediately)time curl -X GET "https://example.com/wp-json/all-sites-cron/v1/run?defer=1"
# Expected: < 1 second response time# Actual processing continues in background3. Check Background Processing
Section titled “3. Check Background Processing”Monitor your server logs for completion message:
tail -f /path/to/php-error.log | grep "All Sites Cron"
# Expected output:# [All Sites Cron] Deferred execution completed: 150 sites processedResponse Examples
Section titled “Response Examples”JSON Mode (defer=1)
Section titled “JSON Mode (defer=1)”{ "success": true, "status": "queued", "message": "Cron job queued for background processing", "timestamp": "2025-10-01 12:00:00", "mode": "deferred"}HTTP Status: 202 Accepted
GitHub Actions Mode (ga=1&defer=1)
Section titled “GitHub Actions Mode (ga=1&defer=1)”::notice::Cron job queued for background processingHTTP Status: 202 Accepted
Synchronous Mode (no defer parameter)
Section titled “Synchronous Mode (no defer parameter)”{ "success": true, "count": 150, "message": "", "timestamp": "2025-10-01 12:00:05", "endpoint": "rest"}HTTP Status: 200 OK
Use Cases
Section titled “Use Cases”✅ When to Use Deferred Mode
Section titled “✅ When to Use Deferred Mode”-
Large Networks (100+ sites)
- Prevents REST API timeouts
- Allows processing to complete without client waiting
-
GitHub Actions / CI/CD
- Workflow completes quickly
- No timeout errors
- Can run more frequently
-
External Monitoring Services
- Services that expect quick responses
- Pingdom, UptimeRobot, cron-job.org, etc.
-
Load Balancers
- Prevents timeout at load balancer level
- Better health check responses
❌ When NOT to Use Deferred Mode
Section titled “❌ When NOT to Use Deferred Mode”-
Small Networks (< 50 sites)
- Synchronous mode is fast enough
- No benefit from deferred processing
-
Debugging / Testing
- Synchronous mode provides immediate feedback
- Easier to see errors and results
-
Sequential Dependencies
- If you need to wait for completion before next action
- Synchronous mode ensures completion
GitHub Actions Configuration
Section titled “GitHub Actions Configuration”Recommended Setup
Section titled “Recommended Setup”name: All Sites Cron Jobon: schedule: - cron: '*/5 * * * *' # Every 5 minutes
env: CRON_ENDPOINT: 'https://example.com/wp-json/all-sites-cron/v1/run?ga=1&defer=1'
jobs: trigger_cron: runs-on: ubuntu-latest timeout-minutes: 2 # Can be reduced with defer mode steps: - name: Trigger Cron run: | curl -X GET ${{ env.CRON_ENDPOINT }} \ --connect-timeout 10 \ --max-time 30 \ --retry 3 \ --retry-delay 5 \ --silent \ --show-error \ --failWhy Use Defer Mode in GitHub Actions?
Section titled “Why Use Defer Mode in GitHub Actions?”- ✅ Prevents workflow timeout errors
- ✅ Faster workflow completion
- ✅ More reliable execution
- ✅ Can reduce
timeout-minutessetting - ✅ Lower GitHub Actions billing (faster = cheaper)
Performance Comparison
Section titled “Performance Comparison”| Mode | Network Size | Response Time | Total Time | Best For |
|---|---|---|---|---|
| Synchronous | 50 sites | 5 seconds | 5 seconds | Small networks |
| Synchronous | 200 sites | 20 seconds | 20 seconds | Medium networks |
| Synchronous | 500 sites | 50 seconds | 50 seconds | Risk of timeout |
| Deferred | 50 sites | < 1 second | 5 seconds* | External triggers |
| Deferred | 200 sites | < 1 second | 20 seconds* | GitHub Actions |
| Deferred | 500 sites | < 1 second | 50 seconds* | Large networks |
* Total time happens in background; client doesn’t wait
Troubleshooting
Section titled “Troubleshooting”Issue: “Connection not closing”
Section titled “Issue: “Connection not closing””Symptom: Request takes full processing time despite defer=1
Solutions:
-
Check if
fastcgi_finish_request()exists:Terminal window php -r "var_dump(function_exists('fastcgi_finish_request'));" -
Verify PHP-FPM is being used:
Terminal window php -i | grep "Server API"# Should show: FPM/FastCGI -
Check for output buffering conflicts in wp-config.php
Issue: “Process killed during background execution”
Section titled “Issue: “Process killed during background execution””Symptom: Cron doesn’t complete on all sites
Solutions:
-
Increase PHP timeout in php.ini:
max_execution_time = 300 -
Check for hosting-level process restrictions
-
Consider reducing
all_sites_cron_batch_sizefilter
Issue: “No log output”
Section titled “Issue: “No log output””Symptom: Can’t see completion message in logs
Solutions:
-
Enable PHP error logging in php.ini:
log_errors = Onerror_log = /path/to/php-error.log -
Check WordPress debug log if WP_DEBUG_LOG is enabled
-
Verify file permissions on log file
Security Considerations
Section titled “Security Considerations”- Authentication (v2.0.0): Optionally protect endpoints with a shared-secret token — see Authentication
- No Additional Risk: Deferred mode uses same permissions as synchronous mode
- Rate Limiting: Still applies (60-second default cooldown)
- Request Locking: Atomic lock prevents concurrent executions
- Log Monitoring: Background execution is logged for auditing
Future Enhancements
Section titled “Future Enhancements”Potential improvements for future versions:
- Queue system with Redis storage (added in v1.5.0, improved in v2.0.0)
- Status endpoint to check background job progress
- Webhook callbacks when processing completes
- Priority queue for specific sites
- Progress tracking API
Support
Section titled “Support”If you encounter issues with deferred mode:
- Check this documentation first
- Test your environment compatibility
- Review server logs for errors
- Open an issue on GitHub with:
- PHP version
- Webserver type and version
- Hosting environment
- Error logs
📦 Source: soderlind/all-sites-cron · Edit on GitHub