{"id":2119,"date":"2025-11-19T00:27:19","date_gmt":"2025-11-18T21:27:19","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/how-to-disable-wp-cron-and-use-real-cron-jobs-for-wordpress-on-cpanel-and-vps\/"},"modified":"2025-11-19T00:27:19","modified_gmt":"2025-11-18T21:27:19","slug":"how-to-disable-wp-cron-and-use-real-cron-jobs-for-wordpress-on-cpanel-and-vps","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/en\/how-to-disable-wp-cron-and-use-real-cron-jobs-for-wordpress-on-cpanel-and-vps\/","title":{"rendered":"How to Disable wp-cron and Use Real Cron Jobs for WordPress on cPanel and VPS"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><p>If you are running a growing WordPress site, you have probably noticed that some things feel a bit \u201cheavier\u201d than they should: slow first page loads, random spikes in CPU usage, or scheduled tasks (like backups or email newsletters) sometimes running late. A surprising amount of this can be traced back to one small but important component: <strong>wp-cron.php<\/strong>, WordPress\u2019s built\u2011in pseudo cron system.<\/p>\n<p>By default, WordPress triggers wp-cron on page views. That sounds convenient, but it quickly becomes a bottleneck on busy sites, and unreliable on low\u2011traffic or cached sites. The fix is simple and very effective: <strong>disable wp-cron\u2019s internal trigger and replace it with a real server\u2011side cron job<\/strong>. On cPanel hosting and <a href=\"https:\/\/www.dchost.com\/vps\">VPS<\/a> servers, this is straightforward once you know the right steps and a few safe practices.<\/p>\n<p>In this guide, we will walk through <strong>why<\/strong> you should do this, <strong>how<\/strong> to disable wp-cron safely, and how to configure <strong>real cron jobs on both cPanel and VPS<\/strong> environments. We will also share practical tips from real\u2011world setups we manage at dchost.com, including testing, troubleshooting, and keeping things reliable as your WordPress sites grow.<\/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=\"#What_wp-cron_Actually_Does_and_Why_It_Becomes_a_Problem\"><span class=\"toc_number toc_depth_1\">1<\/span> What wp-cron Actually Does (and Why It Becomes a Problem)<\/a><ul><li><a href=\"#What_is_wp-cron\"><span class=\"toc_number toc_depth_2\">1.1<\/span> What is wp-cron?<\/a><\/li><li><a href=\"#Why_the_default_wp-cron_behavior_is_inefficient\"><span class=\"toc_number toc_depth_2\">1.2<\/span> Why the default wp-cron behavior is inefficient<\/a><\/li><\/ul><\/li><li><a href=\"#When_You_Should_Switch_to_a_Real_Cron_Job\"><span class=\"toc_number toc_depth_1\">2<\/span> When You Should Switch to a Real Cron Job<\/a><ul><li><a href=\"#Clear_signs_its_time_to_disable_wp-cron\"><span class=\"toc_number toc_depth_2\">2.1<\/span> Clear signs it\u2019s time to disable wp-cron<\/a><\/li><li><a href=\"#When_you_might_NOT_want_to_disable_wp-cron_yet\"><span class=\"toc_number toc_depth_2\">2.2<\/span> When you might NOT want to disable wp-cron (yet)<\/a><\/li><\/ul><\/li><li><a href=\"#Step_1_Safely_Disable_the_Builtin_wp-cron_Trigger\"><span class=\"toc_number toc_depth_1\">3<\/span> Step 1: Safely Disable the Built\u2011in wp-cron Trigger<\/a><ul><li><a href=\"#Before_you_touch_wp-configphp_make_a_backup\"><span class=\"toc_number toc_depth_2\">3.1<\/span> Before you touch wp-config.php: make a backup<\/a><\/li><li><a href=\"#Editing_wp-configphp_to_disable_wp-cron\"><span class=\"toc_number toc_depth_2\">3.2<\/span> Editing wp-config.php to disable wp-cron<\/a><\/li><li><a href=\"#Is_it_safe_to_leave_wp-cron_disabled_without_a_real_cron_job\"><span class=\"toc_number toc_depth_2\">3.3<\/span> Is it safe to leave wp-cron disabled without a real cron job?<\/a><\/li><\/ul><\/li><li><a href=\"#Step_2_Setting_Up_a_Real_Cron_Job_on_cPanel\"><span class=\"toc_number toc_depth_1\">4<\/span> Step 2: Setting Up a Real Cron Job on cPanel<\/a><ul><li><a href=\"#Choosing_how_often_to_run_cron_for_WordPress\"><span class=\"toc_number toc_depth_2\">4.1<\/span> Choosing how often to run cron for WordPress<\/a><\/li><li><a href=\"#Step-by-step_cPanel_Cron_Jobs_interface\"><span class=\"toc_number toc_depth_2\">4.2<\/span> Step-by-step: cPanel Cron Jobs interface<\/a><\/li><li><a href=\"#Option_A_Use_wget_or_curl_to_hit_wp-cron_over_HTTP\"><span class=\"toc_number toc_depth_2\">4.3<\/span> Option A: Use wget or curl to hit wp-cron over HTTP<\/a><\/li><li><a href=\"#Option_B_Use_PHP_CLI_for_advanced_cPanel_setups\"><span class=\"toc_number toc_depth_2\">4.4<\/span> Option B: Use PHP CLI (for advanced cPanel setups)<\/a><\/li><li><a href=\"#Multiple_WordPress_sites_on_one_cPanel_account\"><span class=\"toc_number toc_depth_2\">4.5<\/span> Multiple WordPress sites on one cPanel account<\/a><\/li><\/ul><\/li><li><a href=\"#Step_3_Setting_Up_a_Real_Cron_Job_on_a_VPS\"><span class=\"toc_number toc_depth_1\">5<\/span> Step 3: Setting Up a Real Cron Job on a VPS<\/a><ul><li><a href=\"#Prerequisites_on_your_VPS\"><span class=\"toc_number toc_depth_2\">5.1<\/span> Prerequisites on your VPS<\/a><\/li><li><a href=\"#Deciding_where_to_put_the_cron_entry\"><span class=\"toc_number toc_depth_2\">5.2<\/span> Deciding where to put the cron entry<\/a><\/li><li><a href=\"#Option_A_Call_wp-cronphp_with_PHP_CLI\"><span class=\"toc_number toc_depth_2\">5.3<\/span> Option A: Call wp-cron.php with PHP CLI<\/a><\/li><li><a href=\"#Option_B_Call_wp-cronphp_over_HTTP_with_curlwget\"><span class=\"toc_number toc_depth_2\">5.4<\/span> Option B: Call wp-cron.php over HTTP with curl\/wget<\/a><\/li><li><a href=\"#Multiple_WordPress_sites_on_one_VPS\"><span class=\"toc_number toc_depth_2\">5.5<\/span> Multiple WordPress sites on one VPS<\/a><\/li><\/ul><\/li><li><a href=\"#Security_and_Reliability_Considerations_for_wp-cron\"><span class=\"toc_number toc_depth_1\">6<\/span> Security and Reliability Considerations for wp-cron<\/a><ul><li><a href=\"#Should_you_block_wp-cronphp_from_public_access\"><span class=\"toc_number toc_depth_2\">6.1<\/span> Should you block wp-cron.php from public access?<\/a><\/li><li><a href=\"#Dealing_with_HTTP_authentication_or_maintenance_modes\"><span class=\"toc_number toc_depth_2\">6.2<\/span> Dealing with HTTP authentication or maintenance modes<\/a><\/li><li><a href=\"#wp-cron_and_caching_plugins_reverse_proxies\"><span class=\"toc_number toc_depth_2\">6.3<\/span> wp-cron and caching plugins \/ reverse proxies<\/a><\/li><\/ul><\/li><li><a href=\"#Testing_and_Troubleshooting_Your_New_Cron_Setup\"><span class=\"toc_number toc_depth_1\">7<\/span> Testing and Troubleshooting Your New Cron Setup<\/a><ul><li><a href=\"#Step_1_Verify_WordPress_cron_events_are_scheduled\"><span class=\"toc_number toc_depth_2\">7.1<\/span> Step 1: Verify WordPress cron events are scheduled<\/a><\/li><li><a href=\"#Step_2_Manually_trigger_wp-cron\"><span class=\"toc_number toc_depth_2\">7.2<\/span> Step 2: Manually trigger wp-cron<\/a><\/li><li><a href=\"#Step_3_Watch_your_logs\"><span class=\"toc_number toc_depth_2\">7.3<\/span> Step 3: Watch your logs<\/a><\/li><li><a href=\"#Common_issues_and_quick_fixes\"><span class=\"toc_number toc_depth_2\">7.4<\/span> Common issues and quick fixes<\/a><\/li><\/ul><\/li><li><a href=\"#Advanced_Tips_WP-CLI_systemd_Timers_and_Staging\"><span class=\"toc_number toc_depth_1\">8<\/span> Advanced Tips: WP-CLI, systemd Timers, and Staging<\/a><ul><li><a href=\"#Using_WP-CLI_to_inspect_and_run_cron_events\"><span class=\"toc_number toc_depth_2\">8.1<\/span> Using WP-CLI to inspect and run cron events<\/a><\/li><li><a href=\"#Using_systemd_timers_instead_of_cron_for_advanced_VPS_users\"><span class=\"toc_number toc_depth_2\">8.2<\/span> Using systemd timers instead of cron (for advanced VPS users)<\/a><\/li><li><a href=\"#Handling_staging_and_development_environments\"><span class=\"toc_number toc_depth_2\">8.3<\/span> Handling staging and development environments<\/a><\/li><\/ul><\/li><li><a href=\"#Putting_It_All_Together_A_NoDrama_Cron_Strategy_for_WordPress\"><span class=\"toc_number toc_depth_1\">9<\/span> Putting It All Together: A No\u2011Drama Cron Strategy for WordPress<\/a><\/li><\/ul><\/div>\n<h2><span id=\"What_wp-cron_Actually_Does_and_Why_It_Becomes_a_Problem\">What wp-cron Actually Does (and Why It Becomes a Problem)<\/span><\/h2>\n<h3><span id=\"What_is_wp-cron\">What is wp-cron?<\/span><\/h3>\n<p>In a normal Linux system, <strong>cron<\/strong> is a scheduler that runs commands at fixed times (every 5 minutes, every hour, once a day, and so on). WordPress doesn\u2019t assume your hosting has cron configured for it, so it ships with its own PHP scheduler: <strong>wp-cron.php<\/strong>.<\/p>\n<p>Whenever someone loads a page on your site, WordPress checks whether any scheduled tasks (called <strong>cron events<\/strong>) are due. These can include:<\/p>\n<ul>\n<li>Publishing scheduled posts<\/li>\n<li>Running backup plugins<\/li>\n<li>Clearing caches and transients<\/li>\n<li>Processing WooCommerce orders or subscriptions<\/li>\n<li>Sending email digests or newsletter queues<\/li>\n<li>Sync jobs for SEO, security, or analytics plugins<\/li>\n<\/ul>\n<p>If something is due to run, WordPress triggers <strong>wp-cron.php<\/strong> in the background to process the queue.<\/p>\n<h3><span id=\"Why_the_default_wp-cron_behavior_is_inefficient\">Why the default wp-cron behavior is inefficient<\/span><\/h3>\n<p>On paper this looks convenient, but in production it has several drawbacks:<\/p>\n<ul>\n<li><strong>It runs on page views, not precise time.<\/strong> If nobody visits your site for a while, scheduled tasks may run late or not at all until the next visit.<\/li>\n<li><strong>It can run multiple times in parallel.<\/strong> On busy sites, multiple users may trigger wp-cron at almost the same time, causing duplicate work and extra load.<\/li>\n<li><strong>It adds overhead on user requests.<\/strong> Even though wp-cron tries to run in the background, the check and trigger still add overhead to normal page loads.<\/li>\n<li><strong>It fights with caching\/CDN setups.<\/strong> If you use aggressive page caching or a CDN, the request that should trigger wp-cron might be served entirely from cache, and the scheduler never fires correctly.<\/li>\n<\/ul>\n<p>When we tune high\u2011traffic WordPress sites at dchost.com, disabling the wp-cron trigger and using real cron is almost always one of the early tweaks, right next to PHP\u2011FPM and database tuning. If you\u2019re interested in the broader optimization picture, we cover many of these tactics in our article <a href=\"https:\/\/www.dchost.com\/blog\/en\/wordpress-icin-sunucu-tarafi-optimizasyon-php-fpm-opcache-redis-ve-mysql-ile-neyi-ne-zaman-nasil-ayarlamalisin\/\">the server\u2011side secrets that make WordPress fly<\/a>.<\/p>\n<h2><span id=\"When_You_Should_Switch_to_a_Real_Cron_Job\">When You Should Switch to a Real Cron Job<\/span><\/h2>\n<h3><span id=\"Clear_signs_its_time_to_disable_wp-cron\">Clear signs it\u2019s time to disable wp-cron<\/span><\/h3>\n<p>Almost any serious WordPress site benefits from real cron, but it becomes especially important when:<\/p>\n<ul>\n<li><strong>You have moderate or high traffic.<\/strong> Many visitors mean wp-cron is triggered constantly, wasting CPU and memory.<\/li>\n<li><strong>You rely on scheduled actions.<\/strong> Scheduled posts, WooCommerce subscriptions, membership sites, backups, and email queues need predictability.<\/li>\n<li><strong>You use full\u2011page caching or a CDN.<\/strong> Heavy caching can prevent wp-cron from firing reliably on page views.<\/li>\n<li><strong>You see cron\u2011related slowdowns.<\/strong> PHP workers constantly busy, long TTFB (time to first byte) on random requests, or slow admin screens when cron is running.<\/li>\n<\/ul>\n<h3><span id=\"When_you_might_NOT_want_to_disable_wp-cron_yet\">When you might NOT want to disable wp-cron (yet)<\/span><\/h3>\n<p>There are a few cases where you may not want to switch immediately:<\/p>\n<ul>\n<li><strong>Very small personal sites<\/strong> with almost no plugins, where you are on basic hosting and don\u2019t have access to cron settings.<\/li>\n<li><strong>Some highly managed WordPress platforms<\/strong> that already handle cron for you behind the scenes. In this case, follow their documentation.<\/li>\n<li><strong>Temporary testing environments<\/strong> where you just want something quick and dirty and don\u2019t care about perfect scheduling.<\/li>\n<\/ul>\n<p>On any <strong>cPanel hosting plan or VPS from dchost.com<\/strong>, you have access to proper cron, so switching away from wp-cron is both possible and recommended for production sites.<\/p>\n<h2><span id=\"Step_1_Safely_Disable_the_Builtin_wp-cron_Trigger\">Step 1: Safely Disable the Built\u2011in wp-cron Trigger<\/span><\/h2>\n<h3><span id=\"Before_you_touch_wp-configphp_make_a_backup\">Before you touch wp-config.php: make a backup<\/span><\/h3>\n<p>You will be editing <strong>wp-config.php<\/strong>, which controls core WordPress settings. A small typo here can take your site offline. Before you start, make sure you have:<\/p>\n<ul>\n<li>A recent <strong>file backup<\/strong> of your site (or at least wp-config.php).<\/li>\n<li>A <strong>database backup<\/strong> just in case (not strictly needed for this change, but always nice to have).<\/li>\n<\/ul>\n<p>If you are building a backup plan anyway, it\u2019s worth reading our guide on the <a href=\"https:\/\/www.dchost.com\/blog\/en\/3-2-1-yedekleme-stratejisi-neden-ise-yariyor-cpanel-plesk-ve-vpste-otomatik-yedekleri-nasil-kurarsin\/\">3\u20112\u20111 backup strategy and how to automate backups on cPanel and VPS<\/a>. Cron\u2011based backups and wp-cron scheduling often go hand\u2011in\u2011hand in real setups.<\/p>\n<h3><span id=\"Editing_wp-configphp_to_disable_wp-cron\">Editing wp-config.php to disable wp-cron<\/span><\/h3>\n<p>1. Connect to your hosting account:<\/p>\n<ul>\n<li>On <strong>cPanel hosting<\/strong>: use <strong>cPanel &raquo; File Manager<\/strong> and navigate to your WordPress installation directory (often <code>public_html<\/code>).<\/li>\n<li>On a <strong>VPS<\/strong>: use SSH and <code>cd<\/code> into your site\u2019s document root directory.<\/li>\n<\/ul>\n<p>2. Locate the file <strong>wp-config.php<\/strong> in your WordPress root.<\/p>\n<p>3. Open <strong>wp-config.php<\/strong> for editing.<\/p>\n<p>4. Find the line that looks like this (or something very similar):<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">\/* That's all, stop editing! Happy publishing. *\/<\/code><\/pre>\n<p>5. <strong>Just above that line<\/strong>, add the following constant definition:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">define('DISABLE_WP_CRON', true);<\/code><\/pre>\n<p>So the relevant part of your file will look like:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">define('DISABLE_WP_CRON', true);\n\n\/* That's all, stop editing! Happy publishing. *\/<\/code><\/pre>\n<p>6. Save the file.<\/p>\n<p>From this moment on, WordPress will <strong>no longer automatically trigger wp-cron on page views<\/strong>. Cron events will still exist inside WordPress, but they will only run when we explicitly call <code>wp-cron.php<\/code> from a real cron job.<\/p>\n<h3><span id=\"Is_it_safe_to_leave_wp-cron_disabled_without_a_real_cron_job\">Is it safe to leave wp-cron disabled without a real cron job?<\/span><\/h3>\n<p>Temporarily, yes, but not for long. With wp-cron disabled, scheduled posts will not publish, backups may not run, and WooCommerce subscriptions may not renew until you configure a replacement cron. Plan to add a real cron job immediately after changing this setting.<\/p>\n<h2><span id=\"Step_2_Setting_Up_a_Real_Cron_Job_on_cPanel\">Step 2: Setting Up a Real Cron Job on cPanel<\/span><\/h2>\n<h3><span id=\"Choosing_how_often_to_run_cron_for_WordPress\">Choosing how often to run cron for WordPress<\/span><\/h3>\n<p>In most cases, running WordPress cron every <strong>5 minutes<\/strong> is a solid default. Some very small sites can use 10 or 15 minutes; heavy WooCommerce or membership sites might need 1\u20132 minute intervals. The goal is to <strong>balance freshness with server load<\/strong>\u2014you don\u2019t want to hammer wp-cron every 30 seconds unless there is a real need.<\/p>\n<h3><span id=\"Step-by-step_cPanel_Cron_Jobs_interface\">Step-by-step: cPanel Cron Jobs interface<\/span><\/h3>\n<p>1. Log in to your <strong>cPanel<\/strong> account.<\/p>\n<p>2. In the <strong>Advanced<\/strong> section, click on <strong>Cron Jobs<\/strong>.<\/p>\n<p>3. Under <strong>Add New Cron Job<\/strong>, choose a schedule. For example, to run every 5 minutes:<\/p>\n<ul>\n<li><strong>Common Settings:<\/strong> select \u201cEvery 5 minutes (*\/5 * * * *)\u201d if available; or<\/li>\n<li>Set the fields manually: <code>Minute: *\/5<\/code>, <code>Hour: *<\/code>, <code>Day: *<\/code>, <code>Month: *<\/code>, <code>Weekday: *<\/code>.<\/li>\n<\/ul>\n<h3><span id=\"Option_A_Use_wget_or_curl_to_hit_wp-cron_over_HTTP\">Option A: Use wget or curl to hit wp-cron over HTTP<\/span><\/h3>\n<p>This is the most common method on shared hosting because it doesn\u2019t require SSH or WP-CLI.<\/p>\n<p>In the <strong>Command<\/strong> field, enter something like:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">wget -q -O - https:\/\/example.com\/wp-cron.php?doing_wp_cron &gt; \/dev\/null 2&gt;&amp;1<\/code><\/pre>\n<p>or, if you prefer <code>curl<\/code>:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">curl -s https:\/\/example.com\/wp-cron.php?doing_wp_cron &gt; \/dev\/null 2&gt;&amp;1<\/code><\/pre>\n<p>Replace <code>https:\/\/example.com<\/code> with your site\u2019s real URL (use HTTPS if your site does).<\/p>\n<p>The <code>&gt; \/dev\/null 2&gt;&amp;1<\/code> part discards any output so your email inbox is not filled with cron messages.<\/p>\n<h3><span id=\"Option_B_Use_PHP_CLI_for_advanced_cPanel_setups\">Option B: Use PHP CLI (for advanced cPanel setups)<\/span><\/h3>\n<p>If your hosting allows SSH and you know which PHP binary your site uses, you can call <code>wp-cron.php<\/code> via PHP CLI. This avoids HTTP overhead and some caching complications.<\/p>\n<p>Example command:<\/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>Adjust the path to:<\/p>\n<ul>\n<li>The correct PHP binary (for example <code>\/opt\/cpanel\/ea-php82\/root\/usr\/bin\/php<\/code>).<\/li>\n<li>Your actual document root and WordPress path (for example <code>\/home\/username\/public_html<\/code> or <code>\/home\/username\/sites\/example.com<\/code>).<\/li>\n<\/ul>\n<p>If you are tuning PHP versions and performance, our <a href=\"https:\/\/www.dchost.com\/blog\/en\/php-8-x-yukseltme-kontrol-listesi-wordpress-ve-laravelde-geriye-uyumluluk-opcache-preload-ve-fpm-havuz-ayarlari-nasil-tatli-tatli-kurulur\/\">PHP 8.x upgrade checklist for WordPress<\/a> is a good companion read.<\/p>\n<h3><span id=\"Multiple_WordPress_sites_on_one_cPanel_account\">Multiple WordPress sites on one cPanel account<\/span><\/h3>\n<p>If you host more than one WordPress site under the same cPanel account (for example in <code>public_html\/site1<\/code>, <code>public_html\/site2<\/code>, etc.), you have two main options:<\/p>\n<ul>\n<li><strong>Create one cron job per site<\/strong>, each pointing to its own <code>wp-cron.php<\/code>.<\/li>\n<li><strong>Create a small shell script<\/strong> that calls each site\u2019s <code>wp-cron.php<\/code> in sequence, and schedule that script from a single cron job.<\/li>\n<\/ul>\n<p>For clarity and easier troubleshooting, we usually prefer <strong>one cron job per WordPress installation<\/strong>, especially when you have independent clients or projects on the same account.<\/p>\n<h2><span id=\"Step_3_Setting_Up_a_Real_Cron_Job_on_a_VPS\">Step 3: Setting Up a Real Cron Job on a VPS<\/span><\/h2>\n<h3><span id=\"Prerequisites_on_your_VPS\">Prerequisites on your VPS<\/span><\/h3>\n<p>On a VPS from dchost.com, you have full control over cron. Before you start:<\/p>\n<ul>\n<li>Make sure the <strong>cron service<\/strong> is running (usually <code>crond<\/code> on CentOS\/Alma\/Rocky, or <code>cron<\/code> on Debian\/Ubuntu).<\/li>\n<li>Confirm you know the <strong>PHP CLI path<\/strong> (often <code>\/usr\/bin\/php<\/code>).<\/li>\n<li>Know your site path, e.g. <code>\/var\/www\/example.com\/public<\/code> or <code>\/var\/www\/html<\/code>.<\/li>\n<\/ul>\n<p>On many VPS setups, you might also be running other scheduled jobs (backups, log rotation, monitoring). If you are interested in the broader world of scheduling, we have a dedicated article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/cron-mu-systemd-timer-mi-neden-nasil-ve-ne-zaman-hangisini-secmeli\/\">cron vs. systemd timers and when to use which<\/a>.<\/p>\n<h3><span id=\"Deciding_where_to_put_the_cron_entry\">Deciding where to put the cron entry<\/span><\/h3>\n<p>You can add cron entries in several ways:<\/p>\n<ul>\n<li><strong>User crontab<\/strong>: run <code>crontab -e<\/code> as the user that owns the site\u2019s files (recommended).<\/li>\n<li><strong>Root crontab<\/strong>: run <code>sudo crontab -e<\/code> and specify the user inside the command (more advanced).<\/li>\n<li><strong>\/etc\/crontab or \/etc\/cron.d<\/strong>: for multi\u2011site or configuration\u2011as\u2011code setups.<\/li>\n<\/ul>\n<p>For a single WordPress site on a VPS, using <code>crontab -e<\/code> as that site\u2019s user is typically the cleanest approach.<\/p>\n<h3><span id=\"Option_A_Call_wp-cronphp_with_PHP_CLI\">Option A: Call wp-cron.php with PHP CLI<\/span><\/h3>\n<p>1. SSH into your VPS as the user that owns your WordPress files (or as root if you will specify the user).<\/p>\n<p>2. Run:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">crontab -e<\/code><\/pre>\n<p>3. Add a line like this to run cron every 5 minutes:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">*\/5 * * * * \/usr\/bin\/php -q \/var\/www\/example.com\/public\/wp-cron.php &gt; \/dev\/null 2&gt;&amp;1<\/code><\/pre>\n<p>Adjust the paths:<\/p>\n<ul>\n<li><strong>\/usr\/bin\/php<\/strong>: your PHP CLI path, which you can find with <code>which php<\/code>.<\/li>\n<li><strong>\/var\/www\/example.com\/public<\/strong>: your actual WordPress document root.<\/li>\n<\/ul>\n<p>4. Save and exit the editor (for example, <code>:wq<\/code> in <code>vi<\/code>).<\/p>\n<p>This method is fast and bypasses HTTP, which is nice when you have strict firewalls or are using special origin protection such as <a href=\"https:\/\/www.dchost.com\/blog\/en\/origini-korumak-cloudflare-authenticated-origin-pulls-ve-mtls-ile-gercek-kaynak-dogrulamasi\/\">Cloudflare authenticated origin pulls and mTLS<\/a>.<\/p>\n<h3><span id=\"Option_B_Call_wp-cronphp_over_HTTP_with_curlwget\">Option B: Call wp-cron.php over HTTP with curl\/wget<\/span><\/h3>\n<p>Sometimes you prefer to run cron over HTTP, for example when:<\/p>\n<ul>\n<li>Your WordPress logic depends on <strong>actual HTTP context<\/strong> (rare but possible).<\/li>\n<li>You are running behind a reverse proxy with security or caching logic that needs to see these requests.<\/li>\n<\/ul>\n<p>Example cron entry (in <code>crontab -e<\/code>):<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">*\/5 * * * * curl -s https:\/\/example.com\/wp-cron.php?doing_wp_cron &gt; \/dev\/null 2&gt;&amp;1<\/code><\/pre>\n<p>Again, replace with your real domain and scheme (HTTP vs HTTPS). Ensure that your firewall, WAF, or rate limiting rules don\u2019t block this internal cron traffic; it often helps to whitelist your server\u2019s own IP for this endpoint.<\/p>\n<h3><span id=\"Multiple_WordPress_sites_on_one_VPS\">Multiple WordPress sites on one VPS<\/span><\/h3>\n<p>If your VPS hosts several WordPress projects, you can:<\/p>\n<ul>\n<li>Add <strong>one cron entry per site<\/strong> in each site\u2019s user crontab; or<\/li>\n<li>Create a small shell script (for example <code>\/usr\/local\/bin\/run-all-wordpress-crons.sh<\/code>) that loops over all sites and calls their wp-cron.php, then schedule that script once.<\/li>\n<\/ul>\n<p>For example, a simple script might contain:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">#!\/bin\/bash\n\n\/usr\/bin\/php -q \/var\/www\/site1.com\/public\/wp-cron.php &gt; \/dev\/null 2&gt;&amp;1\n\/usr\/bin\/php -q \/var\/www\/site2.com\/public\/wp-cron.php &gt; \/dev\/null 2&gt;&amp;1\n\/usr\/bin\/php -q \/var\/www\/site3.com\/public\/wp-cron.php &gt; \/dev\/null 2&gt;&amp;1<\/code><\/pre>\n<p>Then your cron entry can simply be:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">*\/5 * * * * \/usr\/local\/bin\/run-all-wordpress-crons.sh<\/code><\/pre>\n<h2><span id=\"Security_and_Reliability_Considerations_for_wp-cron\">Security and Reliability Considerations for wp-cron<\/span><\/h2>\n<h3><span id=\"Should_you_block_wp-cronphp_from_public_access\">Should you block wp-cron.php from public access?<\/span><\/h3>\n<p>Because wp-cron is now called on a schedule, some admins are tempted to block wp-cron.php from public access entirely. Be careful: <strong>some plugins explicitly call wp-cron via HTTP<\/strong>, and blocking it with a firewall rule or .htaccess directive can cause subtle breakage.<\/p>\n<p>A more balanced approach is:<\/p>\n<ul>\n<li>Keep wp-cron.php accessible, but <strong>rate limit or protect it<\/strong> if you are under attack.<\/li>\n<li>Ensure you are not accidentally blocking your own server\u2019s IP with security plugins, WAF rules, or services.<\/li>\n<\/ul>\n<p>If you are hardening your WordPress installation overall, have a look at our <a href=\"https:\/\/www.dchost.com\/blog\/en\/wordpress-guvenlik-sertlestirme-kontrol-listesi-dosya-izinleri-salt-keys-xml-rpc-ufw-fail2ban-nasil-tatli-tatli-kurulur\/\">WordPress hardening checklist<\/a>, which goes deeper into file permissions, firewalling, and brute\u2011force protection.<\/p>\n<h3><span id=\"Dealing_with_HTTP_authentication_or_maintenance_modes\">Dealing with HTTP authentication or maintenance modes<\/span><\/h3>\n<p>If your site is protected by HTTP Basic Auth (for example on a staging environment), your cron command needs credentials. For curl, you can do:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">curl -s -u user:password https:\/\/staging.example.com\/wp-cron.php?doing_wp_cron &gt; \/dev\/null 2&gt;&amp;1<\/code><\/pre>\n<p>For live sites, be careful not to expose credentials in shell history or shared documentation. On VPS setups, you may prefer PHP CLI for that reason.<\/p>\n<h3><span id=\"wp-cron_and_caching_plugins_reverse_proxies\">wp-cron and caching plugins \/ reverse proxies<\/span><\/h3>\n<p>When cron is called over HTTP, make sure your caching setup does <strong>not cache the wp-cron.php response<\/strong>. Most popular caching plugins and reverse proxy rules already respect this, but double\u2011check:<\/p>\n<ul>\n<li>Does your CDN bypass cache for <code>\/wp-cron.php<\/code>?<\/li>\n<li>Does Nginx\/Apache treat it as a dynamic endpoint with no caching?<\/li>\n<\/ul>\n<p>For high\u2011scale setups with edge caching, our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/cdn-onbellekleme-cache-control-ve-edge-kurallari-wordpress-ve-woocommercede-tam-isabet-ayarlar\/\">CDN caching rules for WordPress and WooCommerce<\/a> provides a good framework for getting these exceptions right without sacrificing speed.<\/p>\n<h2><span id=\"Testing_and_Troubleshooting_Your_New_Cron_Setup\">Testing and Troubleshooting Your New Cron Setup<\/span><\/h2>\n<h3><span id=\"Step_1_Verify_WordPress_cron_events_are_scheduled\">Step 1: Verify WordPress cron events are scheduled<\/span><\/h3>\n<p>Install a plugin such as <strong>WP Crontrol<\/strong> to inspect cron events inside WordPress:<\/p>\n<ul>\n<li>Go to <strong>Tools &raquo; Cron Events<\/strong> (or similar, depending on the plugin).<\/li>\n<li>Confirm that you see scheduled events with future run times.<\/li>\n<\/ul>\n<p>If there are no events at all, then either WordPress or your plugins are not scheduling anything\u2014or wp-cron was previously disabled incorrectly.<\/p>\n<h3><span id=\"Step_2_Manually_trigger_wp-cron\">Step 2: Manually trigger wp-cron<\/span><\/h3>\n<p>Run the command you configured in cron <strong>manually<\/strong> from the shell (on VPS) or from your browser (for HTTP\u2011based setups):<\/p>\n<ul>\n<li><strong>HTTP method:<\/strong> visit <code>https:\/\/example.com\/wp-cron.php?doing_wp_cron<\/code> in a browser (while logged out or in incognito to mimic a real request).<\/li>\n<li><strong>PHP CLI method:<\/strong> run <code>\/usr\/bin\/php -q \/var\/www\/example.com\/public\/wp-cron.php<\/code> in the terminal.<\/li>\n<\/ul>\n<p>Then refresh your WordPress cron events page and check if the \u201cnext run\u201d timestamps have advanced as expected.<\/p>\n<h3><span id=\"Step_3_Watch_your_logs\">Step 3: Watch your logs<\/span><\/h3>\n<p>If something is not running correctly, your logs are your best friend:<\/p>\n<ul>\n<li><strong>PHP error log<\/strong> (e.g. <code>error_log<\/code> in your site root, or per\u2011vhost logs).<\/li>\n<li><strong>Web server logs<\/strong> (Nginx\/Apache access and error logs).<\/li>\n<li><strong>System log for cron<\/strong> (often <code>\/var\/log\/cron<\/code> or <code>\/var\/log\/syslog<\/code> depending on the distro).<\/li>\n<\/ul>\n<p>On a VPS, centralizing logs can make this much easier. For a deeper look into this, we have a full playbook on <a href=\"https:\/\/www.dchost.com\/blog\/en\/vps-log-yonetimi-nasil-rayina-oturur-grafana-loki-promtail-ile-merkezi-loglama-tutma-sureleri-ve-alarm-kurallari\/\">VPS log management with Loki, Promtail and Grafana<\/a>.<\/p>\n<h3><span id=\"Common_issues_and_quick_fixes\">Common issues and quick fixes<\/span><\/h3>\n<ul>\n<li><strong>Nothing runs, no errors:<\/strong> Cron service may not be running. Check with <code>systemctl status cron<\/code> or <code>systemctl status crond<\/code>.<\/li>\n<li><strong>\u201cCommand not found\u201d in cron logs:<\/strong> Your command path is wrong. Use absolute paths for PHP, curl, wget, and your WordPress directory.<\/li>\n<li><strong>HTTP 403\/404 for wp-cron.php:<\/strong> Security plugin, WAF, or .htaccess rule might be blocking it. Temporarily disable or adjust the rule.<\/li>\n<li><strong>Scheduled events are missed or bunched together:<\/strong> Run cron more frequently (e.g. from every 15 minutes to every 5 or 2 minutes).<\/li>\n<\/ul>\n<h2><span id=\"Advanced_Tips_WP-CLI_systemd_Timers_and_Staging\">Advanced Tips: WP-CLI, systemd Timers, and Staging<\/span><\/h2>\n<h3><span id=\"Using_WP-CLI_to_inspect_and_run_cron_events\">Using WP-CLI to inspect and run cron events<\/span><\/h3>\n<p>On a VPS with WP-CLI installed, you gain powerful tools for working with cron:<\/p>\n<ul>\n<li><strong>List events:<\/strong> <code>wp cron event list<\/code><\/li>\n<li><strong>Run due events:<\/strong> <code>wp cron event run --due-now<\/code><\/li>\n<li><strong>Run a specific hook:<\/strong> <code>wp cron event run my_custom_hook<\/code><\/li>\n<\/ul>\n<p>You can even replace the call to <code>wp-cron.php<\/code> in your cron entry with a WP-CLI command, although this is more advanced and requires the right PATH, user, and working directory.<\/p>\n<h3><span id=\"Using_systemd_timers_instead_of_cron_for_advanced_VPS_users\">Using systemd timers instead of cron (for advanced VPS users)<\/span><\/h3>\n<p>On modern Linux distributions, <strong>systemd timers<\/strong> can be an alternative to cron, especially when you want more robust logging, dependencies, or on\u2011boot behavior. The logic is the same: call <code>wp-cron.php<\/code> or a WP-CLI command on a schedule. If you want to explore this path, we cover the tradeoffs in our article <a href=\"https:\/\/www.dchost.com\/blog\/en\/cron-mu-systemd-timer-mi-neden-nasil-ve-ne-zaman-hangisini-secmeli\/\">Cron vs systemd timers: when and how to choose each<\/a>.<\/p>\n<h3><span id=\"Handling_staging_and_development_environments\">Handling staging and development environments<\/span><\/h3>\n<p>For staging or development environments, decide whether you <strong>really need cron<\/strong> enabled:<\/p>\n<ul>\n<li>On many staging sites, it\u2019s better to <strong>disable cron completely<\/strong> to avoid sending real emails or running heavy tasks unexpectedly.<\/li>\n<li>If your staging is used to test cron\u2011related features (for example subscription renewals), you can run it at a slower frequency (e.g. every 30 minutes).<\/li>\n<li>Make sure staging URLs are not publicly reachable if they are running real cron jobs that send notifications or integrate with external systems.<\/li>\n<\/ul>\n<h2><span id=\"Putting_It_All_Together_A_NoDrama_Cron_Strategy_for_WordPress\">Putting It All Together: A No\u2011Drama Cron Strategy for WordPress<\/span><\/h2>\n<p>Once you have switched from wp-cron\u2019s page\u2011view trigger to a proper server\u2011side cron job, you will likely notice a few things:<\/p>\n<ul>\n<li>First page loads feel more consistent.<\/li>\n<li>Scheduled posts, WooCommerce renewals, and plugin tasks happen on time.<\/li>\n<li>Your resource usage becomes more predictable, especially under traffic spikes.<\/li>\n<\/ul>\n<p>The complete picture for a healthy WordPress site combines this with <strong>good backups, security hardening, and performance tuning<\/strong>. At dchost.com, we design our shared hosting, VPS, dedicated, and colocation solutions around exactly this kind of real\u2011world workload: predictable cron, fast storage, and the right balance of CPU and RAM for WordPress, WooCommerce, and custom applications.<\/p>\n<p>If you are currently on basic shared hosting without proper cron control, or if your WordPress sites are outgrowing their environment, it might be a good moment to consider moving to a <strong>VPS or higher\u2011end hosting plan<\/strong> where you control scheduling, caching, and PHP versions. When you are ready to plan that move, our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/paylasimli-hostingden-vpse-nasil-gecersin-kesintisiz-tasima-icin-sicacik-bir-kontrol-listesi\/\">migrating from shared hosting to a VPS with zero downtime<\/a> is a practical checklist you can follow.<\/p>\n<p>For now, though, you have taken an important step: <strong>decoupling WordPress cron from page views<\/strong> and letting the server handle scheduling the way it was meant to. Set a reminder to review your cron frequency, check plugin behavior, and keep your backups and security measures in good shape. And if you ever want help tuning WordPress on cPanel, a VPS, or a <a href=\"https:\/\/www.dchost.com\/dedicated-server\">dedicated server<\/a>, our team at dchost.com is here to share the same calm, step\u2011by\u2011step approach we use on our own production systems.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>If you are running a growing WordPress site, you have probably noticed that some things feel a bit \u201cheavier\u201d than they should: slow first page loads, random spikes in CPU usage, or scheduled tasks (like backups or email newsletters) sometimes running late. A surprising amount of this can be traced back to one small but [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2120,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24,33,30,25],"tags":[],"class_list":["post-2119","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hosting","category-nasil-yapilir","category-nedir","category-sunucu"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/2119","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=2119"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/2119\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media\/2120"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media?parent=2119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/categories?post=2119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/tags?post=2119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}