{"id":3914,"date":"2026-01-01T17:27:05","date_gmt":"2026-01-01T14:27:05","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/replacing-wp-cron-php-with-real-cron-on-wordpress\/"},"modified":"2026-01-01T17:27:05","modified_gmt":"2026-01-01T14:27:05","slug":"replacing-wp-cron-php-with-real-cron-on-wordpress","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/en\/replacing-wp-cron-php-with-real-cron-on-wordpress\/","title":{"rendered":"Replacing wp-cron.php with Real Cron on WordPress"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><p>On most WordPress and WooCommerce sites, hundreds of small background tasks keep things running smoothly: order emails, stock updates, subscription renewals, follow-up reminders, database cleanups and more. By default, all of these are driven by <code>wp-cron.php<\/code>, a pseudo-scheduler that only runs when someone visits your site. That design is convenient for cheap hosting, but it is not ideal when you care about reliable timing, heavy traffic, or money-making WooCommerce orders. In this guide, we will walk through why relying only on <code>wp-cron.php<\/code> is risky, what \u201creal\u201d server cron actually does, and how to switch your WordPress site to use proper cron jobs without breaking anything. We will focus on practical setups that work on shared hosting, <a href=\"https:\/\/www.dchost.com\/vps\">VPS<\/a> and <a href=\"https:\/\/www.dchost.com\/dedicated-server\">dedicated server<\/a>s, and we will highlight WooCommerce-specific pitfalls so your orders, emails and inventory stay in sync even during traffic spikes or quiet nights.<\/p>\n<div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">\u0130&ccedil;indekiler<\/p><ul class=\"toc_list\"><li><a href=\"#Why_wp-cronphp_Becomes_a_Problem_for_Real_Sites\"><span class=\"toc_number toc_depth_1\">1<\/span> Why wp-cron.php Becomes a Problem for Real Sites<\/a><ul><li><a href=\"#Low-traffic_sites_missed_or_delayed_jobs\"><span class=\"toc_number toc_depth_2\">1.1<\/span> Low-traffic sites: missed or delayed jobs<\/a><\/li><li><a href=\"#High-traffic_sites_duplicate_and_overlapping_runs\"><span class=\"toc_number toc_depth_2\">1.2<\/span> High-traffic sites: duplicate and overlapping runs<\/a><\/li><li><a href=\"#Why_this_matters_so_much_for_WooCommerce\"><span class=\"toc_number toc_depth_2\">1.3<\/span> Why this matters so much for WooCommerce<\/a><\/li><\/ul><\/li><li><a href=\"#How_WordPress_Scheduling_Works_Behind_the_Scenes\"><span class=\"toc_number toc_depth_1\">2<\/span> How WordPress Scheduling Works Behind the Scenes<\/a><ul><li><a href=\"#WP-Cron_events_in_the_database\"><span class=\"toc_number toc_depth_2\">2.1<\/span> WP-Cron events in the database<\/a><\/li><li><a href=\"#What_triggers_wp-cronphp\"><span class=\"toc_number toc_depth_2\">2.2<\/span> What triggers wp-cron.php?<\/a><\/li><\/ul><\/li><li><a href=\"#Real_Cron_vs_wp-cronphp_What_You_Gain\"><span class=\"toc_number toc_depth_1\">3<\/span> Real Cron vs wp-cron.php: What You Gain<\/a><ul><li><a href=\"#Predictable_timing\"><span class=\"toc_number toc_depth_2\">3.1<\/span> Predictable timing<\/a><\/li><li><a href=\"#Lower_overhead_on_page_loads\"><span class=\"toc_number toc_depth_2\">3.2<\/span> Lower overhead on page loads<\/a><\/li><li><a href=\"#Better_reliability_for_money-critical_workflows\"><span class=\"toc_number toc_depth_2\">3.3<\/span> Better reliability for money-critical workflows<\/a><\/li><li><a href=\"#Plays_nicely_with_background_job_strategy\"><span class=\"toc_number toc_depth_2\">3.4<\/span> Plays nicely with background job strategy<\/a><\/li><\/ul><\/li><li><a href=\"#Preparing_Your_Hosting_or_Server_for_Real_Cron\"><span class=\"toc_number toc_depth_1\">4<\/span> Preparing Your Hosting or Server for Real Cron<\/a><ul><li><a href=\"#Shared_hosting_with_cPanel_or_DirectAdmin\"><span class=\"toc_number toc_depth_2\">4.1<\/span> Shared hosting with cPanel or DirectAdmin<\/a><\/li><li><a href=\"#VPS_dedicated_or_colocated_servers\"><span class=\"toc_number toc_depth_2\">4.2<\/span> VPS, dedicated or colocated servers<\/a><\/li><\/ul><\/li><li><a href=\"#Step_1_Disable_Automatic_wp-cronphp\"><span class=\"toc_number toc_depth_1\">5<\/span> Step 1: Disable Automatic wp-cron.php<\/a><ul><li><a href=\"#Editing_wp-configphp\"><span class=\"toc_number toc_depth_2\">5.1<\/span> Editing wp-config.php<\/a><\/li><li><a href=\"#What_if_you_forget_to_add_real_cron\"><span class=\"toc_number toc_depth_2\">5.2<\/span> What if you forget to add real cron?<\/a><\/li><\/ul><\/li><li><a href=\"#Step_2_Create_a_Real_Cron_Job_for_wp-cronphp\"><span class=\"toc_number toc_depth_1\">6<\/span> Step 2: Create a Real Cron Job for wp-cron.php<\/a><ul><li><a href=\"#Core_command_pattern\"><span class=\"toc_number toc_depth_2\">6.1<\/span> Core command pattern<\/a><\/li><li><a href=\"#cPanel_adding_the_cron_job\"><span class=\"toc_number toc_depth_2\">6.2<\/span> cPanel: adding the cron job<\/a><\/li><li><a href=\"#DirectAdmin_or_similar_panels\"><span class=\"toc_number toc_depth_2\">6.3<\/span> DirectAdmin or similar panels<\/a><\/li><li><a href=\"#Plain_Linux_with_crontab\"><span class=\"toc_number toc_depth_2\">6.4<\/span> Plain Linux with crontab<\/a><\/li><li><a href=\"#Choosing_the_right_frequency\"><span class=\"toc_number toc_depth_2\">6.5<\/span> Choosing the right frequency<\/a><\/li><\/ul><\/li><li><a href=\"#Step_3_Testing_Your_New_Cron_Setup\"><span class=\"toc_number toc_depth_1\">7<\/span> Step 3: Testing Your New Cron Setup<\/a><ul><li><a href=\"#Manual_trigger_from_the_command_line\"><span class=\"toc_number toc_depth_2\">7.1<\/span> Manual trigger from the command line<\/a><\/li><li><a href=\"#Using_WP_Crontrol_to_inspect_events\"><span class=\"toc_number toc_depth_2\">7.2<\/span> Using WP Crontrol to inspect events<\/a><\/li><li><a href=\"#Watching_logs_and_notifications\"><span class=\"toc_number toc_depth_2\">7.3<\/span> Watching logs and notifications<\/a><\/li><\/ul><\/li><li><a href=\"#Multiple_WordPress_Sites_on_One_Server\"><span class=\"toc_number toc_depth_1\">8<\/span> Multiple WordPress Sites on One Server<\/a><ul><li><a href=\"#One_cron_job_per_site\"><span class=\"toc_number toc_depth_2\">8.1<\/span> One cron job per site<\/a><\/li><li><a href=\"#A_central_runner_using_WP-CLI_advanced\"><span class=\"toc_number toc_depth_2\">8.2<\/span> A central runner using WP-CLI (advanced)<\/a><\/li><\/ul><\/li><li><a href=\"#WooCommerce-Specific_Scheduling_Considerations\"><span class=\"toc_number toc_depth_1\">9<\/span> WooCommerce-Specific Scheduling Considerations<\/a><ul><li><a href=\"#Order_status_timeouts_and_cancellations\"><span class=\"toc_number toc_depth_2\">9.1<\/span> Order status timeouts and cancellations<\/a><\/li><li><a href=\"#Subscriptions_and_memberships\"><span class=\"toc_number toc_depth_2\">9.2<\/span> Subscriptions and memberships<\/a><\/li><li><a href=\"#High-traffic_campaigns_and_flash_sales\"><span class=\"toc_number toc_depth_2\">9.3<\/span> High-traffic campaigns and flash sales<\/a><\/li><\/ul><\/li><li><a href=\"#Performance_Locking_and_Safety_Tips\"><span class=\"toc_number toc_depth_1\">10<\/span> Performance, Locking and Safety Tips<\/a><ul><li><a href=\"#Use_the_correct_PHP_binary\"><span class=\"toc_number toc_depth_2\">10.1<\/span> Use the correct PHP binary<\/a><\/li><li><a href=\"#Avoid_overlapping_cron_runs\"><span class=\"toc_number toc_depth_2\">10.2<\/span> Avoid overlapping cron runs<\/a><\/li><li><a href=\"#Keep_an_eye_on_resource_usage\"><span class=\"toc_number toc_depth_2\">10.3<\/span> Keep an eye on resource usage<\/a><\/li><li><a href=\"#Do_not_forget_backups\"><span class=\"toc_number toc_depth_2\">10.4<\/span> Do not forget backups<\/a><\/li><\/ul><\/li><li><a href=\"#When_wp-cronphp_Is_Still_Good_Enough\"><span class=\"toc_number toc_depth_1\">11<\/span> When wp-cron.php Is Still \u201cGood Enough\u201d<\/a><\/li><li><a href=\"#Summary_and_Next_Steps\"><span class=\"toc_number toc_depth_1\">12<\/span> Summary and Next Steps<\/a><\/li><\/ul><\/div>\n<h2><span id=\"Why_wp-cronphp_Becomes_a_Problem_for_Real_Sites\">Why wp-cron.php Becomes a Problem for Real Sites<\/span><\/h2>\n<p><strong>wp-cron.php is not a real scheduler.<\/strong> It is just a PHP file that WordPress tries to call on each page load to check whether any scheduled tasks are due. This brings several problems that show up quickly on production sites.<\/p>\n<h3><span id=\"Low-traffic_sites_missed_or_delayed_jobs\">Low-traffic sites: missed or delayed jobs<\/span><\/h3>\n<p>On a brochure site with a few visits per day, wp-cron might never run at the exact time you scheduled something. If nobody visits your site at 03:00, a \u201crun at 03:00\u201d job may wait until 11:00 when the next visitor arrives.<\/p>\n<ul>\n<li>Abandoned cart emails are sent many hours late.<\/li>\n<li>Daily database cleanups run irregularly, if at all.<\/li>\n<li>Time-limited coupons or sales banners do not change on time.<\/li>\n<\/ul>\n<p>For WooCommerce stores, such delays can directly hit revenue and support workload.<\/p>\n<h3><span id=\"High-traffic_sites_duplicate_and_overlapping_runs\">High-traffic sites: duplicate and overlapping runs<\/span><\/h3>\n<p>On a busy WooCommerce store with many concurrent visitors, the opposite problem appears: <strong>too many wp-cron calls.<\/strong> Multiple visitors may trigger <code>wp-cron.php<\/code> at nearly the same time. While WordPress tries to lock the process, in the real world you often see:<\/p>\n<ul>\n<li>Time-intensive jobs (like huge email batches) running multiple times.<\/li>\n<li>Extra CPU and I\/O pressure because wp-cron starts on top of each page request.<\/li>\n<li>Slow checkout pages because PHP-FPM is busy processing background tasks.<\/li>\n<\/ul>\n<p>This is exactly the kind of hidden load that later shows up as high TTFB, increased 5xx errors, and checkout slowness. If you want to dive deeper into these performance issues, our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/yuksek-ttfb-sorununu-cozmek-wordpress-ve-php-sitelerde-sunucu-tarafli-nedenler-ve-cozumler\/\">fixing high TTFB on WordPress and PHP sites<\/a> is a good companion read.<\/p>\n<h3><span id=\"Why_this_matters_so_much_for_WooCommerce\">Why this matters so much for WooCommerce<\/span><\/h3>\n<p>WooCommerce relies heavily on scheduled tasks to maintain consistency:<\/p>\n<ul>\n<li>Order status transitions (on-hold to cancelled after X minutes, pending payments cleanups).<\/li>\n<li>Stock reservations and release of stock from unpaid orders.<\/li>\n<li>Subscription renewals and recurring payments (via WooCommerce Subscriptions or similar plugins).<\/li>\n<li>Follow-up emails, coupon expirations, membership access windows.<\/li>\n<\/ul>\n<p>If wp-cron runs too late, not at all, or multiple times, you can end up with:<\/p>\n<ul>\n<li>Customers receiving duplicate or missing emails.<\/li>\n<li>Incorrect stock numbers or overselling during campaigns.<\/li>\n<li>Subscriptions not renewing on time, leading to support tickets.<\/li>\n<\/ul>\n<p>That is why one of the first reliability upgrades we recommend for serious WooCommerce sites on our infrastructure is to <strong>disable wp-cron.php and move to real cron<\/strong>.<\/p>\n<h2><span id=\"How_WordPress_Scheduling_Works_Behind_the_Scenes\">How WordPress Scheduling Works Behind the Scenes<\/span><\/h2>\n<p>Before changing anything, it helps to know what is happening under the hood.<\/p>\n<h3><span id=\"WP-Cron_events_in_the_database\">WP-Cron events in the database<\/span><\/h3>\n<p>WordPress stores scheduled events in the <code>wp_options<\/code> table under a special option called <code>cron<\/code>. Each event has:<\/p>\n<ul>\n<li>a timestamp (when it should next run),<\/li>\n<li>a hook name (e.g. <code>woocommerce_cancel_unpaid_orders<\/code>),<\/li>\n<li>optional arguments, and<\/li>\n<li>a recurrence (single run or repeating interval).<\/li>\n<\/ul>\n<p>When <code>wp-cron.php<\/code> runs, WordPress loads that data, finds due events, and fires the corresponding hooks, which plugins listen to.<\/p>\n<h3><span id=\"What_triggers_wp-cronphp\">What triggers wp-cron.php?<\/span><\/h3>\n<p>On each normal page load, WordPress checks if there are overdue events. If yes, it tries to call <code>wp-cron.php<\/code> asynchronously (using a loopback HTTP request). This means:<\/p>\n<ul>\n<li>Cron can start only when there is traffic.<\/li>\n<li>Cron runs via HTTP, not directly via PHP CLI on the server.<\/li>\n<li>Firewall or authentication settings sometimes block this internal HTTP call.<\/li>\n<\/ul>\n<p>When we introduce <strong>real cron<\/strong>, we still rely on the same internal scheduling system (events, hooks, <code>wp_options<\/code> row). The only difference is <em>how<\/em> <code>wp-cron.php<\/code> is triggered: by the server\u2019s scheduler instead of visitors.<\/p>\n<h2><span id=\"Real_Cron_vs_wp-cronphp_What_You_Gain\">Real Cron vs wp-cron.php: What You Gain<\/span><\/h2>\n<p>A real cron job is a native system scheduler entry (on Linux or via your hosting panel) that runs commands at fixed times, regardless of traffic. When you replace automatic wp-cron with a real cron job, you keep all of WordPress\u2019 scheduling logic but improve how it is launched.<\/p>\n<h3><span id=\"Predictable_timing\">Predictable timing<\/span><\/h3>\n<p>With real cron, you control exactly when <code>wp-cron.php<\/code> runs. Examples:<\/p>\n<ul>\n<li>Every 5 minutes for order processing and email queues.<\/li>\n<li>Every minute during a big campaign if you have heavy queues.<\/li>\n<li>Once at 03:00 for nightly backups or maintenance tasks.<\/li>\n<\/ul>\n<p>Tasks run even if nobody visits your site, which is critical for scheduled promotions or delayed workflows.<\/p>\n<h3><span id=\"Lower_overhead_on_page_loads\">Lower overhead on page loads<\/span><\/h3>\n<p>Once you disable the automatic wp-cron trigger, every front-end or admin request becomes lighter:<\/p>\n<ul>\n<li>No more additional HTTP loopback requests to <code>wp-cron.php<\/code>.<\/li>\n<li>Less CPU spikes during busy hours.<\/li>\n<li>Fewer random slow requests caused by cron tasks starting mid-visit.<\/li>\n<\/ul>\n<p>On WooCommerce stores, this helps keep checkout fast and stable, especially when combined with tuned PHP-FPM settings and database optimization. If you are planning for bigger traffic, our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/woocommerce-kapasite-planlama-rehberi-vcpu-ram-iops-nasil-hesaplanir\/\">WooCommerce capacity planning for vCPU, RAM and IOPS<\/a> is worth reviewing alongside cron changes.<\/p>\n<h3><span id=\"Better_reliability_for_money-critical_workflows\">Better reliability for money-critical workflows<\/span><\/h3>\n<p>Payment confirmation emails, invoice generation, subscription renewals and stock synchronizations should not depend on whether a random visitor happens to load a page. With real cron, these workflows become:<\/p>\n<ul>\n<li><strong>Deterministic:<\/strong> they always run at the defined interval.<\/li>\n<li><strong>Auditable:<\/strong> you can log or monitor cron runs from the system side.<\/li>\n<li><strong>Easier to debug:<\/strong> because you can manually rerun the cron command from SSH.<\/li>\n<\/ul>\n<h3><span id=\"Plays_nicely_with_background_job_strategy\">Plays nicely with background job strategy<\/span><\/h3>\n<p>If you are already thinking about queues, workers and other background processes on your VPS, replacing wp-cron is a natural step. We discussed why background jobs matter and how to design them in our guide <a href=\"https:\/\/www.dchost.com\/blog\/en\/vps-uzerinde-arka-plan-isleri-ve-kuyruk-yonetimi-laravel-queue-supervisor-systemd-ve-pm2\/\">why background jobs matter so much on a VPS<\/a>. WordPress and WooCommerce scheduling should be treated with the same seriousness.<\/p>\n<h2><span id=\"Preparing_Your_Hosting_or_Server_for_Real_Cron\">Preparing Your Hosting or Server for Real Cron<\/span><\/h2>\n<p>The exact steps differ a bit depending on where your WordPress runs, but the principle is the same: disable auto wp-cron, then create a system cron entry that calls <code>wp-cron.php<\/code> at the interval you choose.<\/p>\n<h3><span id=\"Shared_hosting_with_cPanel_or_DirectAdmin\">Shared hosting with cPanel or DirectAdmin<\/span><\/h3>\n<p>On most decent shared hosting plans (including those at dchost.com), you have a \u201cCron Jobs\u201d or \u201cScheduled Tasks\u201d section in the control panel. This lets you:<\/p>\n<ul>\n<li>Specify the execution interval (e.g. every 5 minutes).<\/li>\n<li>Run a PHP command pointing to your WordPress <code>wp-cron.php<\/code>.<\/li>\n<li>Optionally receive email if the cron job outputs errors.<\/li>\n<\/ul>\n<p>If you would like a screenshot-level tutorial, we have a separate walkthrough on <a href=\"https:\/\/www.dchost.com\/blog\/en\/wordpresste-wp-cron-devre-disi-birakma-ve-gercek-cron-job-kurulumu\/\">disabling wp-cron and using real cron jobs for WordPress on cPanel and VPS<\/a>. In this article we will stay a bit more platform-neutral and focus on concepts and safe patterns.<\/p>\n<h3><span id=\"VPS_dedicated_or_colocated_servers\">VPS, dedicated or colocated servers<\/span><\/h3>\n<p>On a VPS or dedicated\/colocation server, you have direct access to the system scheduler (crontab). This gives you more flexibility:<\/p>\n<ul>\n<li>Run cron via the PHP CLI binary you choose (matching your FPM version).<\/li>\n<li>Use <code>crontab -e<\/code> to edit schedules per-user, or system-wide.<\/li>\n<li>Combine WordPress cron runs with other maintenance and backup schedules.<\/li>\n<\/ul>\n<p>If you are new to Linux cron, our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/linux-crontab-en-iyi-uygulamalar-rehberi-yedek-rapor-ve-bakim-isleri-icin-guvenli-zamanlama\/\">Linux crontab best practices for safe backups, reports and maintenance<\/a> covers log handling, locking and other precautions that also apply to WordPress cron.<\/p>\n<h2><span id=\"Step_1_Disable_Automatic_wp-cronphp\">Step 1: Disable Automatic wp-cron.php<\/span><\/h2>\n<p>The first step is to stop WordPress from trying to trigger cron on every page load. This is done by adding one line to <code>wp-config.php<\/code>.<\/p>\n<h3><span id=\"Editing_wp-configphp\">Editing wp-config.php<\/span><\/h3>\n<p>Open <code>wp-config.php<\/code> in your site\u2019s root directory and add the following line <strong>above<\/strong> the line that says <code>\/* That's all, stop editing! *\/<\/code>:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">define('DISABLE_WP_CRON', true);<\/code><\/pre>\n<p>Save the file and upload it if you edited it locally. From this moment on:<\/p>\n<ul>\n<li>WordPress will <strong>no longer<\/strong> try to call <code>wp-cron.php<\/code> automatically on page loads.<\/li>\n<li>All scheduled events are still stored in the database as before.<\/li>\n<li>It becomes <strong>your job<\/strong> to run <code>wp-cron.php<\/code> via real cron.<\/li>\n<\/ul>\n<h3><span id=\"What_if_you_forget_to_add_real_cron\">What if you forget to add real cron?<\/span><\/h3>\n<p>If you set <code>DISABLE_WP_CRON<\/code> to <code>true<\/code> but do not add a system cron job, scheduled tasks will not run at all. New orders will still be accepted, but background tasks like cleaning pending orders or sending scheduled emails can stop. So always treat this change and the next step (creating real cron) as a single operation.<\/p>\n<h2><span id=\"Step_2_Create_a_Real_Cron_Job_for_wp-cronphp\">Step 2: Create a Real Cron Job for wp-cron.php<\/span><\/h2>\n<p>Now we will set up the actual cron job that will call <code>wp-cron.php<\/code> on a fixed schedule.<\/p>\n<h3><span id=\"Core_command_pattern\">Core command pattern<\/span><\/h3>\n<p>The most robust pattern on Linux-based hosting is to run <code>wp-cron.php<\/code> through the PHP CLI:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">\/usr\/bin\/php -q \/home\/USERNAME\/public_html\/wp-cron.php &gt;\/dev\/null 2&gt;&amp;1<\/code><\/pre>\n<p>Explanation:<\/p>\n<ul>\n<li><code>\/usr\/bin\/php<\/code> \u2013 path to PHP CLI (check with <code>which php<\/code> on a VPS).<\/li>\n<li><code>-q<\/code> \u2013 quiet mode (no HTTP headers).<\/li>\n<li><code>\/home\/USERNAME\/public_html\/wp-cron.php<\/code> \u2013 full filesystem path to your site\u2019s <code>wp-cron.php<\/code>.<\/li>\n<li><code>&gt;\/dev\/null 2&gt;&amp;1<\/code> \u2013 discard output to avoid filling your inbox or logs unless there is a problem you are actively debugging.<\/li>\n<\/ul>\n<h3><span id=\"cPanel_adding_the_cron_job\">cPanel: adding the cron job<\/span><\/h3>\n<ol>\n<li>Log in to cPanel and open <strong>Cron Jobs<\/strong>.<\/li>\n<li>In the &#8220;Add New Cron Job&#8221; section, pick a common setting like &#8220;Every 5 minutes&#8221; or choose custom values:<\/li>\n<\/ol>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">*\/5 * * * * \/usr\/bin\/php -q \/home\/USERNAME\/public_html\/wp-cron.php &gt;\/dev\/null 2&gt;&amp;1<\/code><\/pre>\n<ol start=\"3\">\n<li>Replace <code>USERNAME<\/code> and the path to match your hosting account.<\/li>\n<li>Save. The job will now run every 5 minutes.<\/li>\n<\/ol>\n<h3><span id=\"DirectAdmin_or_similar_panels\">DirectAdmin or similar panels<\/span><\/h3>\n<p>Other panels (DirectAdmin, Plesk, etc.) have a similar &#8220;Cron&#8221; or &#8220;Scheduled Tasks&#8221; section. The core command is the same; only the interface differs. Paste the <code>\/usr\/bin\/php ... wp-cron.php<\/code> command and set the interval to 5 minutes as a starting point.<\/p>\n<h3><span id=\"Plain_Linux_with_crontab\">Plain Linux with crontab<\/span><\/h3>\n<p>On a VPS or dedicated server without a panel, you can add cron jobs directly from the shell:<\/p>\n<ol>\n<li>SSH into your server.<\/li>\n<li>Run <code>crontab -e<\/code> as the user that owns your WordPress files (often the same user that runs PHP-FPM for that site).<\/li>\n<li>Add a line like this:<\/li>\n<\/ol>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">*\/5 * * * * \/usr\/bin\/php -q \/var\/www\/example.com\/public_html\/wp-cron.php &gt;\/dev\/null 2&gt;&amp;1<\/code><\/pre>\n<ol start=\"4\">\n<li>Save and exit. Cron will pick up the new schedule automatically.<\/li>\n<\/ol>\n<p>If you are designing a more advanced VPS stack, our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/vps-uzerinde-arka-plan-isleri-ve-kuyruk-yonetimi-laravel-queue-supervisor-systemd-ve-pm2\/\">background jobs and queue management on a VPS<\/a> also gives you ideas on structuring systemd units and supervisors around cron-driven workloads.<\/p>\n<h3><span id=\"Choosing_the_right_frequency\">Choosing the right frequency<\/span><\/h3>\n<p>How often should you run <code>wp-cron.php<\/code>? It depends on your site\u2019s profile:<\/p>\n<ul>\n<li><strong>Small blogs or corporate sites:<\/strong> every 10\u201315 minutes is usually enough.<\/li>\n<li><strong>Standard WooCommerce store:<\/strong> every 5 minutes is a good balance.<\/li>\n<li><strong>High-order-volume stores or heavy email automation:<\/strong> every 1\u20132 minutes during peak hours can make sense.<\/li>\n<\/ul>\n<p>You can also run multiple cron entries with different frequencies if needed (e.g. a fast one for queue processing and a daily one for heavy reports), but in most WordPress setups, a single 5-minute cron is sufficient.<\/p>\n<h2><span id=\"Step_3_Testing_Your_New_Cron_Setup\">Step 3: Testing Your New Cron Setup<\/span><\/h2>\n<p>Before you forget about it, you should verify that the new cron job is actually running and that WordPress events are being processed.<\/p>\n<h3><span id=\"Manual_trigger_from_the_command_line\">Manual trigger from the command line<\/span><\/h3>\n<p>If you have SSH access, run the command manually once:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">\/usr\/bin\/php -q \/var\/www\/example.com\/public_html\/wp-cron.php<\/code><\/pre>\n<p>If the command finishes quickly and does not output errors, WordPress cron is executing. If you see PHP errors, fix these first before relying on cron.<\/p>\n<h3><span id=\"Using_WP_Crontrol_to_inspect_events\">Using WP Crontrol to inspect events<\/span><\/h3>\n<p>A popular debugging approach is to temporarily install the WP Crontrol plugin:<\/p>\n<ul>\n<li>Go to <strong>Tools \u2192 Cron Events<\/strong>.<\/li>\n<li>Check the &#8220;Next run&#8221; times of scheduled hooks.<\/li>\n<li>Wait a few minutes after your new cron job has run.<\/li>\n<li>Refresh and confirm that &#8220;Next run&#8221; timestamps move forward as expected.<\/li>\n<\/ul>\n<p>This is especially helpful for confirming that WooCommerce-specific events (like <code>woocommerce_cleanup_sessions<\/code> or <code>woocommerce_cancel_unpaid_orders<\/code>) are running on schedule.<\/p>\n<h3><span id=\"Watching_logs_and_notifications\">Watching logs and notifications<\/span><\/h3>\n<p>During the first days, you might want cron to send output to an email address rather than <code>\/dev\/null<\/code>. Simply remove the <code>&gt;\/dev\/null 2&gt;&amp;1<\/code> part and set a valid email in your panel. Once you are confident everything works, you can switch back to discarding normal output to avoid spammy notifications.<\/p>\n<h2><span id=\"Multiple_WordPress_Sites_on_One_Server\">Multiple WordPress Sites on One Server<\/span><\/h2>\n<p>If you host many WordPress sites on the same server (agencies, freelancers, or multi-brand companies), you have two main strategies.<\/p>\n<h3><span id=\"One_cron_job_per_site\">One cron job per site<\/span><\/h3>\n<p>The simplest and most common approach is:<\/p>\n<ul>\n<li>Create a separate cron entry for each WordPress install.<\/li>\n<li>Point each entry to that site\u2019s own <code>wp-cron.php<\/code>.<\/li>\n<li>Set the frequency according to each site\u2019s needs (e.g. busy WooCommerce stores every 2\u20135 minutes, simple blogs every 15 minutes).<\/li>\n<\/ul>\n<p>This keeps sites isolated. A spike in scheduled tasks on one site does not delay cron for others.<\/p>\n<h3><span id=\"A_central_runner_using_WP-CLI_advanced\">A central runner using WP-CLI (advanced)<\/span><\/h3>\n<p>If you are comfortable with WP-CLI, you can centralize cron execution:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">*\/5 * * * * \/usr\/local\/bin\/wp cron event run --due-now --path=\/var\/www\/site1 &amp;&amp; \n             \/usr\/local\/bin\/wp cron event run --due-now --path=\/var\/www\/site2 &amp;&amp; \n             \/usr\/local\/bin\/wp cron event run --due-now --path=\/var\/www\/site3<\/code><\/pre>\n<p>Here, WP-CLI directly runs due events via <code>cron event run --due-now<\/code>, bypassing <code>wp-cron.php<\/code>. This gives you finer control and clearer exit statuses, but it is an advanced pattern and requires WP-CLI installed system-wide.<\/p>\n<p>For agencies hosting dozens of WordPress sites on one stack, combining real cron with good isolation and monitoring is key. Our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/ajanslar-ve-freelancerlar-icin-hosting-mimarisi-20-wordpress-sitesini-tek-altyapida-guvenle-yonetmek\/\">hosting architecture for agencies managing 20+ WordPress sites on one infrastructure<\/a> dives deeper into this topic.<\/p>\n<h2><span id=\"WooCommerce-Specific_Scheduling_Considerations\">WooCommerce-Specific Scheduling Considerations<\/span><\/h2>\n<p>Once real cron is in place, you can tune it to keep WooCommerce order flows smooth.<\/p>\n<h3><span id=\"Order_status_timeouts_and_cancellations\">Order status timeouts and cancellations<\/span><\/h3>\n<p>WooCommerce uses scheduled events to cancel unpaid orders after a configurable time. With unreliable wp-cron, those cancellations can be delayed for hours or happen in a messy burst. Real cron running every few minutes gives you:<\/p>\n<ul>\n<li>Timely cancellation of unpaid orders, freeing reserved stock.<\/li>\n<li>Predictable email sequences around these changes.<\/li>\n<li>Cleaner reporting because old &#8220;pending&#8221; orders are not hanging around indefinitely.<\/li>\n<\/ul>\n<h3><span id=\"Subscriptions_and_memberships\">Subscriptions and memberships<\/span><\/h3>\n<p>Plugins like WooCommerce Subscriptions and various membership tools rely heavily on cron to:<\/p>\n<ul>\n<li>Generate renewal orders.<\/li>\n<li>Charge stored payment methods via gateways.<\/li>\n<li>Activate or deactivate access based on start\/end dates.<\/li>\n<\/ul>\n<p>Real cron significantly reduces support tickets like \u201cmy subscription did not renew\u201d or \u201cI paid but did not get access\u201d, because the scheduler is no longer tied to random visits.<\/p>\n<h3><span id=\"High-traffic_campaigns_and_flash_sales\">High-traffic campaigns and flash sales<\/span><\/h3>\n<p>During big campaigns or flash sales, WooCommerce stores can experience:<\/p>\n<ul>\n<li>Sudden spikes in orders and session data.<\/li>\n<li>Bigger background workloads (events, emails, stock updates).<\/li>\n<\/ul>\n<p>Combining a solid cron strategy with database tuning helps keep checkout responsive. For larger catalogs and heavier stores, have a look at our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/woocommerce-ve-buyuk-katalog-siteleri-icin-mysql-indeksleme-ve-sorgu-optimizasyonu-rehberi\/\">MySQL indexing and query optimization for WooCommerce<\/a>; it pairs very well with real cron for keeping order processing smooth.<\/p>\n<h2><span id=\"Performance_Locking_and_Safety_Tips\">Performance, Locking and Safety Tips<\/span><\/h2>\n<p>Replacing wp-cron is not just about adding one line to <code>crontab<\/code>. A few extra details make the setup more robust and easier to operate.<\/p>\n<h3><span id=\"Use_the_correct_PHP_binary\">Use the correct PHP binary<\/span><\/h3>\n<p>On some servers, <code>\/usr\/bin\/php<\/code> might be a different version than the one used by your web server (PHP-FPM). Ideally, you want the CLI version to match the FPM version. Check with:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">\/usr\/bin\/php -v<\/code><\/pre>\n<p>If the version is different, consult your hosting documentation or support to find the right CLI path (for example, <code>\/opt\/php82\/bin\/php<\/code>).<\/p>\n<h3><span id=\"Avoid_overlapping_cron_runs\">Avoid overlapping cron runs<\/span><\/h3>\n<p>If your scheduled tasks occasionally take longer than the cron interval (e.g. a large newsletter send), two runs can overlap. Some plugins handle this with internal locking, but to be safe you can introduce a simple lockfile mechanism around your cron command on a VPS:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">*\/5 * * * * flock -n \/tmp\/wp-cron.lock \/usr\/bin\/php -q \/var\/www\/example.com\/public_html\/wp-cron.php &gt;\/dev\/null 2&gt;&amp;1<\/code><\/pre>\n<p><code>flock -n \/tmp\/wp-cron.lock<\/code> ensures that if one cron run is still executing, the next scheduled one will exit immediately instead of piling up.<\/p>\n<h3><span id=\"Keep_an_eye_on_resource_usage\">Keep an eye on resource usage<\/span><\/h3>\n<p>On busy WooCommerce sites, cron can generate noticeable CPU, RAM and I\/O load during heavy processing (e.g. bulk updates, big imports, marketing automation). Monitoring tools like htop, Netdata or a full Prometheus\/Grafana stack help you spot patterns. Our starter guide to <a href=\"https:\/\/www.dchost.com\/blog\/en\/vps-izleme-ve-alarm-kurulumu-prometheus-grafana-ve-uptime-kuma-ile-baslangic\/\">VPS monitoring and alerts with Prometheus, Grafana and Uptime Kuma<\/a> shows how to build a calm, informative monitoring setup around cron and other workloads.<\/p>\n<h3><span id=\"Do_not_forget_backups\">Do not forget backups<\/span><\/h3>\n<p>Changing scheduling often goes hand-in-hand with improving backup routines. Real cron gives you a perfect place to hook nightly database and file backups. On managed panels this is often automated, but on VPS or dedicated servers, you can combine WordPress cron with database dumps and off-site backups triggered from the same crontab. If you need a structured approach, our 3-2-1 backup strategy and automation guides on the blog will help you design a safe plan.<\/p>\n<h2><span id=\"When_wp-cronphp_Is_Still_Good_Enough\">When wp-cron.php Is Still \u201cGood Enough\u201d<\/span><\/h2>\n<p>Not every site must immediately migrate to real cron. wp-cron.php can be acceptable if:<\/p>\n<ul>\n<li>Your site has very low complexity (simple blog or one-page site).<\/li>\n<li>You have no WooCommerce or subscription\/membership logic.<\/li>\n<li>Small delays in scheduled tasks do not matter.<\/li>\n<\/ul>\n<p>Even then, keep in mind that most shared hosting panels make real cron very easy to configure. So if you are already editing <code>wp-config.php<\/code> and you have access to Cron Jobs in your panel, it is usually worth spending an extra minute to set up a proper schedule. Future you will be happy when you add WooCommerce, forms, or marketing plugins later.<\/p>\n<h2><span id=\"Summary_and_Next_Steps\">Summary and Next Steps<\/span><\/h2>\n<p>Replacing WordPress\u2019 default wp-cron mechanism with a real server cron job is one of those small infrastructure changes that dramatically improves reliability without adding ongoing complexity. You keep WordPress\u2019 familiar scheduling model, but you move the trigger from \u201conly when someone visits\u201d to \u201cexactly when the server decides\u201d. For WooCommerce stores, this means more predictable order processing, on-time subscription renewals, fewer double emails, and more consistent stock levels. For busy blogs and content sites, it eliminates random slow requests and makes background cleanups easier to monitor.<\/p>\n<p>At dchost.com we strongly encourage customers running serious WordPress and WooCommerce workloads to make this switch early in the project, alongside other basics like correct PHP-FPM tuning, database optimization and a sound backup strategy. If you are using our shared hosting, VPS, dedicated or colocation services and want help determining the right cron interval or command for your setup, our support team can review your environment and suggest a safe configuration. Once real cron is in place and tested, you can move on to the next optimizations\u2014object caching, database indexing, and scaling plans\u2014knowing that your scheduled tasks are finally running on a solid foundation.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>On most WordPress and WooCommerce sites, hundreds of small background tasks keep things running smoothly: order emails, stock updates, subscription renewals, follow-up reminders, database cleanups and more. By default, all of these are driven by wp-cron.php, a pseudo-scheduler that only runs when someone visits your site. That design is convenient for cheap hosting, but it [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3915,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-3914","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teknoloji"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/3914","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/comments?post=3914"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/3914\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media\/3915"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media?parent=3914"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/categories?post=3914"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/tags?post=3914"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}