<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Getwebup</title>
    <description>The latest articles on DEV Community by Getwebup (@getwebup).</description>
    <link>https://dev.to/getwebup</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4137206%2Fc0f6d13f-7fe3-474b-83bf-0472b790338d.png</url>
      <title>DEV Community: Getwebup</title>
      <link>https://dev.to/getwebup</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/getwebup"/>
    <language>en</language>
    <item>
      <title>PHP 8.5 in cPanel: What's New and How to Upgrade Safely</title>
      <dc:creator>Getwebup</dc:creator>
      <pubDate>Wed, 28 Oct 2026 23:20:14 +0000</pubDate>
      <link>https://dev.to/getwebup/php-85-in-cpanel-whats-new-and-how-to-upgrade-safely-29fd</link>
      <guid>https://dev.to/getwebup/php-85-in-cpanel-whats-new-and-how-to-upgrade-safely-29fd</guid>
      <description>&lt;p&gt;PHP 8.5 has been out since November 2025, and if you're still running PHP 8.1 or 8.2 on your cPanel hosting, you're closer to an unsupported version than you might think. Here's what's actually new in 8.5, why your MultiPHP Manager might not show it yet, and how to move up without a support ticket at midnight.&lt;/p&gt;

&lt;h2&gt;
  
  
  Symptom: PHP 8.5 Isn't in Your MultiPHP Manager Dropdown
&lt;/h2&gt;

&lt;p&gt;You log into cPanel, open &lt;strong&gt;MultiPHP Manager&lt;/strong&gt;, and the highest version listed is 8.3 or 8.4. You've read that 8.5 is out, maybe even seen a plugin changelog mention it, but your account simply doesn't offer it as an option.&lt;/p&gt;

&lt;p&gt;That's not a bug on your end. It's almost always one of these two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your hosting provider's EasyApache 4 (WHM) hasn't pulled in the PHP 8.5 SCL package yet.&lt;/li&gt;
&lt;li&gt;Your account is on shared hosting where the server admin controls which PHP versions get compiled server-wide, and 8.5 hasn't been added to that list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If 8.5 isn't in your list, ask your host which PHP versions your server offers. On a cPanel VPS you control the EasyApache 4 profile yourself, so you can add 8.5 whenever you're ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause: Why cPanel Lags a Few Weeks Behind a PHP Release
&lt;/h2&gt;

&lt;p&gt;EasyApache 4 doesn't compile PHP from source for every account — it installs pre-built SCL (Software Collections) packages maintained by CloudLinux/cPanel's build system. Those packages need every commonly-used PHP extension to compile cleanly against the new version first, especially ionCube Loader, which is a closed-source binary that has to be rebuilt by ionCube themselves after each PHP release. If ionCube hasn't shipped an 8.5 build yet, most cPanel providers hold off adding 8.5 to the general rollout, because half their customers on licensed themes and plugins would break immediately.&lt;/p&gt;

&lt;p&gt;That lag is a feature, not a delay for its own sake — it's the difference between "PHP 8.5 works" and "PHP 8.5 works except for the WooCommerce extension license checker nobody remembers installing."&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Actually New in PHP 8.5
&lt;/h2&gt;

&lt;p&gt;Nothing here forces code changes on its own — 8.5 is a lighter release than 8.4 was. A few additions worth knowing about before you upgrade:&lt;/p&gt;

&lt;h3&gt;
  
  
  The pipe operator (&lt;code&gt;|&amp;gt;&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;You can now chain function calls left-to-right instead of nesting them inside out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before&lt;/span&gt;
&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'trim'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

&lt;span class="c1"&gt;// PHP 8.5&lt;/span&gt;
&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$items&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'trim'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;array_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arrow functions on the right of &lt;code&gt;|&amp;gt;&lt;/code&gt; must be wrapped in parentheses, as above; PHP 8.5 rejects the chain without them.&lt;/p&gt;

&lt;p&gt;Nice for readability, but existing code doesn't need to be rewritten — it's purely additive syntax.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;array_first()&lt;/code&gt; and &lt;code&gt;array_last()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;No more &lt;code&gt;reset($arr)&lt;/code&gt; / &lt;code&gt;end($arr)&lt;/code&gt; gymnastics that mutate the array's internal pointer as a side effect. These two return the first/last value directly without touching pointer state, which matters if you were ever bitten by a stray &lt;code&gt;current()&lt;/code&gt; call returning the wrong element after a &lt;code&gt;reset()&lt;/code&gt; somewhere else in the request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Closures in constant expressions
&lt;/h3&gt;

&lt;p&gt;You can now use a static closure in a constant expression: a class constant, a default parameter or property value, or an attribute argument. Mostly relevant to framework and library authors; unlikely to affect a typical WordPress or WooCommerce stack.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;#[\NoDiscard]&lt;/code&gt; attribute
&lt;/h3&gt;

&lt;p&gt;Lets a function author mark a return value as one that shouldn't be silently thrown away — PHP emits a warning if you call the function without using the result. If a library you depend on adopts this, watch your error log for new warnings that a return value should be used; they're warnings, not fatal errors.&lt;/p&gt;

&lt;p&gt;None of these are breaking changes. The bigger practical question for a hosting account isn't "what's new" — it's "what stopped being supported."&lt;/p&gt;

&lt;h2&gt;
  
  
  PHP Version Support: Where You Actually Stand
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Released&lt;/th&gt;
&lt;th&gt;Status as of mid-2026&lt;/th&gt;
&lt;th&gt;What it means for you&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PHP 8.1&lt;/td&gt;
&lt;td&gt;Nov 2021&lt;/td&gt;
&lt;td&gt;End of life — no security patches&lt;/td&gt;
&lt;td&gt;Upgrade now, not on your next slow week&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PHP 8.2&lt;/td&gt;
&lt;td&gt;Dec 2022&lt;/td&gt;
&lt;td&gt;Security-fixes-only phase&lt;/td&gt;
&lt;td&gt;Plan the move within the next few months&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PHP 8.3&lt;/td&gt;
&lt;td&gt;Nov 2023&lt;/td&gt;
&lt;td&gt;Security-fixes-only phase&lt;/td&gt;
&lt;td&gt;Still fine, but active feature support has ended&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PHP 8.4&lt;/td&gt;
&lt;td&gt;Nov 2024&lt;/td&gt;
&lt;td&gt;Actively supported&lt;/td&gt;
&lt;td&gt;Safe default for most sites right now&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PHP 8.5&lt;/td&gt;
&lt;td&gt;Nov 2025&lt;/td&gt;
&lt;td&gt;Actively supported (newest)&lt;/td&gt;
&lt;td&gt;Fine to test on staging; wait if your stack has licensed plugins that haven't confirmed compatibility&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If MultiPHP Manager shows your account still running 8.1, that's the one to fix first — not because 8.5 has some feature you need, but because 8.1 no longer gets patched against newly discovered vulnerabilities at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix: Upgrading Without Breaking Anything
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Check what's actually installed.&lt;/strong&gt; In WHM, go to &lt;em&gt;Software &amp;gt; MultiPHP Manager&lt;/em&gt; and note every domain's current version. On a VPS with root access you can list the same from the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;whmapi1 php_get_installed_versions
whmapi1 php_get_vhost_versions   &lt;span class="c"&gt;# the PHP version of each domain&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2 — Confirm ionCube and premium extensions support the target version.&lt;/strong&gt; If any theme or plugin license checker depends on ionCube Loader, check ionCube's own compatibility page before switching a production domain. This one step avoids many "site went white after PHP upgrade" problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — Clone to a staging subdomain first.&lt;/strong&gt; cPanel's WordPress Toolkit (if you're on WordPress) or a manual file+database copy to a subdomain both work. Switch the staging copy's PHP version in MultiPHP Manager and load every major page type — home, a product/post page, checkout if it's WooCommerce, and wp-admin.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 — Watch the error log while testing, not after.&lt;/strong&gt; Tail it live during your staging test instead of checking it the next day:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/public_html/error_log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deprecation notices are fine to leave for later cleanup. &lt;code&gt;PHP Fatal error&lt;/code&gt; or &lt;code&gt;PHP Parse error&lt;/code&gt; entries mean don't switch the live site yet — go fix that plugin or theme first, or hold at 8.4 until it's patched.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5 — Switch the live domain, then re-check the log for the first 15 minutes.&lt;/strong&gt; Most real breakage shows up on the very first page load after the switch, not hours later. If something's wrong, MultiPHP Manager lets you roll back to the previous version in seconds — there's no migration to undo, since PHP version is just a routing setting, not a data change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Breakage After the Switch
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ionCube-licensed themes/plugins go white-screen.&lt;/strong&gt; The loader hasn't been rebuilt for the new PHP version yet. Roll back until ionCube ships an updated build, or contact the plugin vendor for their timeline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An abandoned plugin throws a fatal error on activation.&lt;/strong&gt; Usually a function PHP removed several versions ago finally getting called. Deactivate it and look for a maintained alternative — code that was already deprecated in 8.1/8.2 was living on borrowed time regardless of when you upgraded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A custom &lt;code&gt;functions.php&lt;/code&gt; snippet from years ago breaks.&lt;/strong&gt; It's usually a five-minute fix once you can see the actual error instead of a blank screen — which is exactly why Step 4 above matters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prevention: Make the Next Upgrade a Non-Event
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep one PHP version behind the newest release on production unless you have a specific reason to be on the bleeding edge — let the ecosystem catch up first.&lt;/li&gt;
&lt;li&gt;Set a recurring reminder to check MultiPHP Manager every few months rather than waiting for a security-support deadline to force your hand.&lt;/li&gt;
&lt;li&gt;Retire plugins and themes that haven't shipped an update in over a year. If they can't keep up with PHP releases, they're a growing liability regardless of what version you're on today.&lt;/li&gt;
&lt;li&gt;Keep a staging subdomain around permanently instead of spinning one up under pressure — it turns "should I upgrade?" into a five-minute check instead of a weekend project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PHP 8.5 itself isn't a scary upgrade — it's a quiet release with a few nice additions and almost nothing that breaks working code outright. The risk was never really the new version; it's whatever hasn't been touched since PHP 7.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is PHP 8.5 available on my shared hosting yet?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check MultiPHP Manager in cPanel — it lists every PHP version your server offers. If 8.5 isn't there, ask your host which versions your server has.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need to rewrite my code to move to PHP 8.5?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. PHP 8.5 is additive — new syntax like the pipe operator and array_first()/array_last() are optional. Existing code that ran fine on 8.4 will almost always run fine on 8.5 without changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What PHP version should I actually be running right now?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PHP 8.4 is the safe default for most sites in mid-2026. PHP 8.1 is end-of-life with no security patches, so move off it first regardless of whether you go to 8.4 or 8.5.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My site broke after switching PHP versions in MultiPHP Manager. How do I undo it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go back into MultiPHP Manager and select the previous PHP version for that domain. It takes effect immediately with no data loss, since switching versions only changes how PHP executes your existing files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did my licensed theme or plugin go white-screen after the upgrade?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is almost always ionCube Loader not yet rebuilt for the new PHP version. Roll back to your previous PHP version and check ionCube's compatibility page before trying again.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://www.getwebup.in/blog/php-8-5-in-cpanel-what-s-new-and-how-to-upgrade-safely/" rel="noopener noreferrer"&gt;Getwebup blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was created with the help of AI.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>cpanel</category>
      <category>wordpress</category>
      <category>webdev</category>
    </item>
    <item>
      <title>VPS vs Shared Hosting: Which One Do You Actually Need?</title>
      <dc:creator>Getwebup</dc:creator>
      <pubDate>Wed, 28 Oct 2026 23:14:20 +0000</pubDate>
      <link>https://dev.to/getwebup/vps-vs-shared-hosting-which-one-do-you-actually-need-346b</link>
      <guid>https://dev.to/getwebup/vps-vs-shared-hosting-which-one-do-you-actually-need-346b</guid>
      <description>&lt;p&gt;This is the most common upgrade decision in hosting, and it's usually made for the wrong reason — a site feels slow, so the assumption is "I need more power," when the real fix is a caching plugin that costs nothing. Here's how to actually tell whether shared hosting is the bottleneck, or whether it's something a bigger plan won't fix either.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Shared Hosting Actually Is
&lt;/h2&gt;

&lt;p&gt;One physical (or virtual) server, split across many customer accounts, each with its own &lt;code&gt;cPanel&lt;/code&gt; login and its own slice of CPU, RAM, and disk I/O — enforced by something like CloudLinux's LVE limits, which cap how much of the shared machine any one account can consume. You don't get root, you don't touch the OS, and you don't see or affect other accounts on the box. In exchange, it's cheap, it's zero-maintenance, and for a huge number of sites, it's genuinely enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Changes on a VPS
&lt;/h2&gt;

&lt;p&gt;A VPS gives you root access to your own operating system, with a fixed allocation of vCPU and RAM isolated from other customers, though on most plans CPU time is still shared fairly with neighbours (VDS-style plans pin dedicated cores to you). That's the whole trade: more control and more consistent resources, in exchange for more responsibility (unless you pay for managed support) and a higher price.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signs You've Actually Outgrown Shared Hosting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You keep hitting resource limits during normal traffic&lt;/strong&gt; - not just during a launch-day spike, but on an average Tuesday. If your host's control panel shows you repeatedly maxing your CPU or entry-process limit under everyday load, a bigger shared plan just delays the same wall.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need software the shared environment won't allow&lt;/strong&gt; - a background job queue, a non-PHP runtime, a database engine your host doesn't offer, or a service that needs to listen on its own port. Shared hosting is sandboxed on purpose; if your app needs to step outside that sandbox, no shared plan will let it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need root for a real reason&lt;/strong&gt; - custom PHP extensions, a specific server config your host's shared environment doesn't expose, or compliance requirements around what's installed on the machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Noisy neighbours" are a recurring, provable issue&lt;/strong&gt; - if you can show (via your host's own resource-usage reporting) that you're within your allocated limits and still seeing inconsistent performance, that's a shared-hosting-specific problem a VPS's reserved resources actually solves.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Before You Upgrade, Rule These Out
&lt;/h2&gt;

&lt;p&gt;A slow site on shared hosting is very often NOT a shared-hosting problem. Check these first — they cost nothing and fix the same symptom a VPS migration is often used to paper over:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No caching.&lt;/strong&gt; A database-backed CMS (WordPress, most PHP apps) hitting MySQL on every single request will be slow on a VPS too if nothing is cached. A page cache or object cache plugin is usually the single biggest speed fix available, on any hosting tier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unoptimised images and no CDN.&lt;/strong&gt; Large, unresized images are a bigger drag on load time than CPU headroom, on shared hosting or not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A plugin or query actually causing the slowdown.&lt;/strong&gt; Check your host's resource usage graphs for what's actually spiking - it's frequently one runaway process or one missing database index, not a fundamental lack of capacity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Honest Cost Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Factor&lt;/th&gt;
&lt;th&gt;Shared hosting&lt;/th&gt;
&lt;th&gt;VPS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Typical monthly cost (India)&lt;/td&gt;
&lt;td&gt;₹99 – ₹500&lt;/td&gt;
&lt;td&gt;₹450 – ₹5,000+ depending on specs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server management&lt;/td&gt;
&lt;td&gt;Fully handled by the host&lt;/td&gt;
&lt;td&gt;Your job, unless you pay for managed support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Root / custom software&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource guarantee&lt;/td&gt;
&lt;td&gt;Fair-use share of a shared box&lt;/td&gt;
&lt;td&gt;Reserved vCPU/RAM, yours alone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setup effort&lt;/td&gt;
&lt;td&gt;Minimal - upload and go&lt;/td&gt;
&lt;td&gt;OS hardening, firewall, ongoing patching if unmanaged&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The real cost of a VPS isn't just the monthly bill - it's the time (or the managed-support fee) that goes into keeping a server patched and secure. Budget for whichever one you're actually going to pay.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Middle Ground
&lt;/h2&gt;

&lt;p&gt;If the honest answer is "I want more headroom but I don't want to manage a Linux box," a managed VPS is built exactly for that gap - root access stays available for the specific things you need it for, while OS updates, security patching, and monitoring stay with the host. It costs more than unmanaged, but it's still a different trade-off than fully-managed shared hosting: you keep the control that made you look at a VPS in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  If You Decide to Move: A Realistic Checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Provision the VPS and secure it first&lt;/strong&gt;, before migrating anything - root password or SSH keys, a firewall allowing only the ports you need, and OS updates applied.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install the stack your site actually needs&lt;/strong&gt; - web server, PHP or your runtime, database engine, matching versions to what's running on shared hosting to avoid surprises.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy files and export/import the database&lt;/strong&gt; onto the new server without touching DNS yet, so the live site keeps serving traffic while you work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test the site on the new server&lt;/strong&gt; using a hosts-file override or a temporary subdomain pointed at its IP, checking forms, logins, and anything database-dependent, not just that the homepage loads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set up backups on the new server&lt;/strong&gt; before you need them, not after - shared hosting often includes this by default, and it's easy to forget it's now your job.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lower your DNS TTL a day or two ahead&lt;/strong&gt;, then switch the DNS record once testing passes, and watch error logs closely for the following 24-48 hours while propagation completes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Will moving to a VPS automatically make my site faster?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not by itself. If the actual bottleneck is an uncached database query or unoptimised images, that problem follows you to a VPS. A VPS fixes resource-limit problems and lets you fix performance problems yourself (caching, tuning) that shared hosting's sandbox might have prevented.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I move from shared hosting to a VPS without downtime?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mostly, yes, with planning: set up the new VPS, migrate your files and database, test the site there (using a hosts-file override or staging subdomain), and only switch DNS once everything checks out. DNS propagation itself takes time, which is the main unavoidable transition window.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need to know Linux server administration for a VPS?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For an unmanaged VPS, yes - enough to apply security updates, configure a firewall, and troubleshoot a service that won't start. A managed VPS plan removes most of that requirement by keeping the OS-level work with the host.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's actually enforced on shared hosting that isn't on a VPS?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Resource caps (CPU seconds, concurrent processes, memory per account - typically via CloudLinux LVE), restrictions on what software you can install or run, and no access to server-level configuration like php.ini beyond what the panel exposes. A VPS removes all three because you have root.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is a VPS overkill for a small business website?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the site is mostly static content or a standard CMS with moderate traffic, shared hosting is usually the right fit and a VPS is unnecessary cost and responsibility. A VPS earns its keep when you need root, a specific runtime, or resources shared hosting's fair-use limits won't provide.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://www.getwebup.in/blog/vps-vs-shared-hosting-which-one-do-you-need/" rel="noopener noreferrer"&gt;Getwebup blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was created with the help of AI.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vps</category>
      <category>hosting</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>How Much Does VPS Hosting Cost in India?</title>
      <dc:creator>Getwebup</dc:creator>
      <pubDate>Wed, 28 Oct 2026 23:13:53 +0000</pubDate>
      <link>https://dev.to/getwebup/how-much-does-vps-hosting-cost-in-india-5djf</link>
      <guid>https://dev.to/getwebup/how-much-does-vps-hosting-cost-in-india-5djf</guid>
      <description>&lt;p&gt;There's no single answer to "what does a VPS cost," because the honest answer depends on six or seven variables that two different pricing pages rarely present the same way. What follows is what actually moves the number, roughly what the Indian market looks like bracket by bracket, and — more usefully — what to check before you trust a comparison between two quotes. Specific numbers below are broad, current-market brackets, not any one provider's price list; they move over time, so check live pricing before you budget against them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Drives the Price
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;vCPU, RAM and disk.&lt;/strong&gt; The baseline resource spec is still the biggest lever. Doubling RAM or vCPU roughly (not exactly) doubles the entry cost at most providers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disk type.&lt;/strong&gt; NVMe costs more to provide than SATA SSD, which costs more than spinning disk (rare now, but still sold cheap). NVMe's IOPS advantage is real for database-heavy workloads, not just a marketing line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bandwidth allowance.&lt;/strong&gt; Some plans include a generous or unlimited transfer allowance; others cap it and charge for overage. A cheap headline price with a small included allowance can end up costing more than a slightly pricier plan with room to spare.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managed vs unmanaged.&lt;/strong&gt; Managed support - the host handling OS patching, monitoring, and security - typically adds a flat monthly fee on top of the base VPS price. It's real, ongoing work, and providers price it as such.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Region.&lt;/strong&gt; A server in an Indian datacentre avoids the cross-border latency (and sometimes the currency) of a server in Singapore or the US. Indian regions aren't automatically cheaper, but they remove the exchange-rate variable entirely if the provider bills in rupees.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixed tiers vs build-your-own.&lt;/strong&gt; Some providers sell a handful of named plans; others let you size vCPU, RAM, disk and bandwidth independently. Neither is "better" pricing - but comparing a fixed tier against a custom build only works if you match the actual specs, not just the sticker price.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Typical Brackets in the Indian Market
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Typical monthly range&lt;/th&gt;
&lt;th&gt;Typical specs&lt;/th&gt;
&lt;th&gt;Fits&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Entry&lt;/td&gt;
&lt;td&gt;Under ₹500&lt;/td&gt;
&lt;td&gt;1-2 vCPU, 1-4 GB RAM, 25-40 GB SSD/NVMe&lt;/td&gt;
&lt;td&gt;Small apps, dev/test boxes, low-traffic sites&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mid-range&lt;/td&gt;
&lt;td&gt;₹500 - ₹2,000&lt;/td&gt;
&lt;td&gt;2-4 vCPU, 4-8 GB RAM, 50-100 GB&lt;/td&gt;
&lt;td&gt;Production sites and apps with real traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Higher-spec&lt;/td&gt;
&lt;td&gt;₹2,000 - ₹6,000+&lt;/td&gt;
&lt;td&gt;4-8+ vCPU, 8-32 GB RAM, 100 GB+&lt;/td&gt;
&lt;td&gt;Databases, multiple services, higher concurrency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Managed support add-on&lt;/td&gt;
&lt;td&gt;Typically ₹1,000 - ₹3,000/mo on top&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Anyone who doesn't want to own OS patching&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are broad brackets across the market, not a quote - always check a provider's live pricing page for the current number, since these shift with hardware costs, competition and currency over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Often Left Off the Headline Price
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GST.&lt;/strong&gt; Indian providers billing India-registered customers typically add 18% GST on top of the quoted figure - check whether a price is shown inclusive or exclusive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backups.&lt;/strong&gt; Some providers include automated backups; others charge separately per GB or per snapshot. This one is easy to miss until you actually need to restore something.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bandwidth overage.&lt;/strong&gt; Check what happens past the included transfer allowance - metered per GB, throttled, or simply not enforced in practice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A dedicated IPv4 address.&lt;/strong&gt; Increasingly billed separately as IPv4 addresses get scarcer; some plans include one, others don't.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows Server licensing.&lt;/strong&gt; A Windows VPS often carries a separate licence cost on top of the base Linux-equivalent price, sometimes bundled free for an introductory period and billed after.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Foreign vs Indian Billing
&lt;/h2&gt;

&lt;p&gt;A number of well-known VPS providers bill in USD even when they have an Indian datacentre region. That means the rupee amount on your card statement moves with the exchange rate month to month, and your bank typically adds a foreign-transaction fee on top - and a USD invoice isn't the document an Indian business needs for GST input credit. If predictable, reconcilable billing matters to your accounting, an India-billed, GST-invoiced provider removes that variable entirely, independent of which one is technically cheaper on paper.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Actually Compare Two Quotes
&lt;/h2&gt;

&lt;p&gt;Match vCPU, RAM, disk type and size, and bandwidth allowance side by side before comparing the price - not the plan name. Then add GST if it isn't already included, add managed support if you'll actually need it, and check what a dedicated IP and backups cost if they're not bundled. Two plans that look ₹200 apart on the homepage can end up nearly identical, or wildly different, once all of that is priced in the same way.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Worked Example
&lt;/h2&gt;

&lt;p&gt;Say you're moving a mid-traffic WordPress store off shared hosting because you keep hitting resource limits during sales. A realistic starting point is 2 vCPU, 4 GB RAM and 50-80 GB of NVMe or SSD disk - enough headroom for WooCommerce plus a page cache without immediately maxing out. In the brackets above that lands in the mid-range tier, typically ₹500-₹2,000 a month before GST. Add managed support if nobody on your team wants to own security patching, and budget separately for backups if they're not included - the total is usually still well under what a single missed sale during downtime would cost, which is the actual comparison worth making.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Number Changes as You Grow
&lt;/h2&gt;

&lt;p&gt;Most providers let you resize a VPS upward without migrating to new hardware - more vCPU and RAM at the next pricing step, usually with a reboot rather than real downtime. That means the entry price you start at isn't a ceiling; it's fine to start smaller than you think you'll need and resize once you have real usage data, rather than pre-paying for headroom you're guessing at. The exception is disk: most platforms let disk grow but not shrink, so it's worth sizing that one a little more generously up front.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is cheaper VPS hosting always worse?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not necessarily - a lower price can reflect genuinely leaner overhead, a smaller resource allocation that's honestly disclosed, or a promotional rate. It's worth being cautious of a price that's dramatically below the market bracket for the specs advertised, since that's more often where a fair-use limit or oversold hardware shows up later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does VPS pricing include GST in India?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It depends on the provider - some show GST-inclusive pricing, others show the base price and add 18% GST at checkout. Always check which one you're looking at before comparing two numbers, since an 18% difference easily flips which quote is actually cheaper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why do some VPS plans cost more for the same vCPU and RAM?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Usually disk type (NVMe vs SATA SSD), the included bandwidth allowance, whether DDoS protection is bundled or a paid add-on, the region, and whether the price includes managed support. Matching all of those before comparing is the only way the price comparison means anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is billing in USD ever cheaper than billing in INR for an Indian customer?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It can be, depending on the exchange rate at the time and the provider's own pricing - but it adds ongoing currency risk to a recurring bill, and your bank's foreign-transaction fee (commonly 1.5-3.5%) usually eats into any headline saving. It also won't produce the GST invoice an Indian business needs for input credit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How much does managed support typically add to a VPS price?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It varies by provider and by how much is actually managed, but a flat monthly add-on in the low thousands of rupees is a common range for a standard VPS. Weigh it against the time you'd otherwise spend patching and monitoring the server yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should I pick the cheapest VPS that meets my minimum specs?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Only after checking bandwidth allowance, backup policy, DDoS protection, and whether support is included - a plan that's cheaper on vCPU/RAM alone can cost more once you add the things a pricier plan bundled in from the start.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://www.getwebup.in/blog/how-much-does-vps-hosting-cost-in-india/" rel="noopener noreferrer"&gt;Getwebup blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was created with the help of AI.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vps</category>
      <category>hosting</category>
      <category>india</category>
      <category>devops</category>
    </item>
    <item>
      <title>ERR_SOCKET_NOT_CONNECTED: Causes and the Fix</title>
      <dc:creator>Getwebup</dc:creator>
      <pubDate>Wed, 28 Oct 2026 23:02:08 +0000</pubDate>
      <link>https://dev.to/getwebup/errsocketnotconnected-causes-and-the-fix-4i2j</link>
      <guid>https://dev.to/getwebup/errsocketnotconnected-causes-and-the-fix-4i2j</guid>
      <description>&lt;p&gt;ERR_SOCKET_NOT_CONNECTED comes from inside Chrome, not from the network. It means the browser reached for a socket it believed was open, and found it was not - so the request was never sent. Once you know that, the search space collapses to your own machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is almost always local
&lt;/h2&gt;

&lt;p&gt;Chrome keeps a pool of open connections and reuses them, which is why a second page on the same site loads faster than the first. If something closes one of those pooled sockets without Chrome noticing - a proxy, an inspecting antivirus, a VPN cycling, or the OS reclaiming it - the next request that picks it up fails at the moment of writing. The server was never contacted, so nothing about the server can explain it.&lt;/p&gt;

&lt;p&gt;Confirm it in one step: load the same URL in a different browser. If Firefox or Edge opens it, you are debugging Chrome, not a website.&lt;/p&gt;

&lt;h2&gt;
  
  
  On a phone (Android or iPhone)
&lt;/h2&gt;

&lt;p&gt;Most people who search this error are on a phone, where the desktop steps further down don't all apply. Same idea, phone version: make Chrome open fresh connections, and take anything that sits between Chrome and the network out of the way. Try these in order and reload after each:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Switch networks for a moment.&lt;/strong&gt; Turn Wi-Fi off and load the page on mobile data, or the other way round. Or switch airplane mode on for ten seconds and off again. Either way Chrome has to open new connections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Close Chrome completely, then reopen it.&lt;/strong&gt; On Android: Settings &amp;gt; Apps &amp;gt; Chrome &amp;gt; Force stop. On iPhone: swipe Chrome away in the app switcher.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn off any VPN, ad blocker or "security" app that filters traffic.&lt;/strong&gt; Many of them work as a VPN on the phone itself. On Android a key icon in the status bar means one is running; on iPhone, look under Settings &amp;gt; VPN. If the page loads with it off, that app is the cause.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear Chrome's cached files.&lt;/strong&gt; In Chrome: menu (⋮) &amp;gt; Settings &amp;gt; Privacy and security &amp;gt; Delete browsing data, tick "Cached images and files" only, and delete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If it only happens inside another app&lt;/strong&gt; (a link opened from Instagram, WhatsApp or a shopping app): open the same link in Chrome itself, from that app's menu. If Chrome loads it, update Chrome and, on Android, "Android System WebView" from the Play Store. In-app browsers use WebView.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Still failing on both Wi-Fi and mobile data, with every filtering app off? Then it's worth checking whether the site itself is down. See the one case where it is not local below.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fixes, in the order worth trying them
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Flush the socket pools
&lt;/h3&gt;

&lt;p&gt;This directly clears the state the error is about, and it is instant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome://net-internals/#sockets   →  Flush socket pools
chrome://net-internals/#dns       →  Clear host cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do both, then reload. For a one-off, this is usually the whole fix.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Test in incognito with extensions disabled
&lt;/h3&gt;

&lt;p&gt;Incognito runs without most extensions by default, which makes it a fast test rather than a fix. If the page loads there, an extension is intercepting connections. Ad blockers with network-level filtering, VPN extensions, and privacy tools that route requests are the usual candidates. Re-enable them one at a time to find which.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Check the proxy configuration
&lt;/h3&gt;

&lt;p&gt;A stale proxy setting is one of the most common non-obvious causes, particularly a leftover from software that has since been uninstalled. On Windows, look under Settings → Network &amp;amp; Internet → Proxy and turn off both "Automatically detect settings" and any manual proxy you are not deliberately using. On macOS the same lives under Network → Details → Proxies. From a terminal on Windows you can see what is configured with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;netsh winhttp show proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and clear it with &lt;code&gt;netsh winhttp reset proxy&lt;/code&gt; from an elevated prompt.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Look at security software
&lt;/h3&gt;

&lt;p&gt;Antivirus products that scan HTTPS traffic sit between Chrome and the network by design, terminating connections and re-establishing them. When that machinery misbehaves, this error is one of the symptoms. Disable HTTPS or web scanning specifically, rather than the whole product, load the page once, and turn it back on. If that was the cause, add an exception instead of running unprotected.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Reset Chrome's network state
&lt;/h3&gt;

&lt;p&gt;If the error persists across restarts, reset the browser's networking configuration. Chrome's settings have a "Restore settings to their original defaults" option that clears the proxy configuration, extensions and cached network state together. Bookmarks and saved passwords are kept.&lt;/p&gt;

&lt;p&gt;On Windows it is also worth resetting the OS network stack, which clears Winsock layers that third-party software has inserted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="nb"&gt;netsh&lt;/span&gt; &lt;span class="kd"&gt;winsock&lt;/span&gt; &lt;span class="nb"&gt;reset&lt;/span&gt;
&lt;span class="nb"&gt;netsh&lt;/span&gt; &lt;span class="kd"&gt;int&lt;/span&gt; &lt;span class="kd"&gt;ip&lt;/span&gt; &lt;span class="nb"&gt;reset&lt;/span&gt;
&lt;span class="nb"&gt;ipconfig&lt;/span&gt; &lt;span class="na"&gt;/flushdns
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reboot afterwards - these do not take effect until you do.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one case where it is not local
&lt;/h2&gt;

&lt;p&gt;If several people on different networks report the same error on the same site at the same time, look at whatever sits in front of the origin. A load balancer or CDN that accepts a connection and then drops it without a response can leave Chrome holding exactly the kind of dead socket that produces this. Test the origin directly to separate the two:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s1"&gt;'%{http_code}\n'&lt;/span&gt; &lt;span class="nt"&gt;--resolve&lt;/span&gt; yourdomain.com:443:ORIGIN_IP https://yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the origin answers cleanly and the public hostname does not, the proxy layer is where to look. If both answer, you are back to a client-side cause and the list above applies.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How do I fix ERR_SOCKET_NOT_CONNECTED on my phone?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Switch between Wi-Fi and mobile data (or toggle airplane mode), fully close and reopen Chrome, and turn off any VPN, ad-blocking or security app that filters traffic. If the error only appears inside another app's browser, open the link in Chrome and update Chrome and Android System WebView from the Play Store.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is the website down when I see this?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Almost never. This error is raised inside Chrome's own networking layer when it finds a socket in an unusable state, before or as the request is written. Load the same URL in a different browser - if it works, the site is fine and Chrome's state is the problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does it only happen in Chrome?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because it is Chrome's own error string, raised by its socket pooling. Chrome reuses connections aggressively, and a pooled socket that was closed by a proxy or by security software can be picked up and written to before Chrome notices it is dead. Other browsers pool differently and surface the same underlying event as a reset or a generic failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Could a proxy setting cause this even if I do not use a proxy?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes. A proxy configuration left behind by uninstalled software, or a PAC script that no longer resolves, will silently break connections. Check the system proxy settings and turn off automatic proxy detection, which is a frequent culprit on Windows machines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I disabled my extensions and it still happens. What next?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Look at software outside the browser: HTTPS-inspecting antivirus, corporate endpoint agents, and VPN clients all intercept connections at the socket level. Disable them one at a time, load the page, and re-enable. If the error stops for one of them, the fix is an exception in that product rather than leaving it off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does resetting Chrome's settings fix it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It often does, because it clears the proxy configuration, extension state and network settings together. Try the targeted steps first - flushing socket pools and testing in incognito - since a full reset also discards things you may want to keep.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://www.getwebup.in/blog/err-socket-not-connected-causes-and-the-fix/" rel="noopener noreferrer"&gt;Getwebup blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was created with the help of AI.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>networking</category>
      <category>webdev</category>
      <category>troubleshooting</category>
    </item>
    <item>
      <title>Call to Undefined Function in PHP: Enable the Missing Extension</title>
      <dc:creator>Getwebup</dc:creator>
      <pubDate>Wed, 28 Oct 2026 23:01:51 +0000</pubDate>
      <link>https://dev.to/getwebup/call-to-undefined-function-in-php-enable-the-missing-extension-27n</link>
      <guid>https://dev.to/getwebup/call-to-undefined-function-in-php-enable-the-missing-extension-27n</guid>
      <description>&lt;p&gt;You switch a site to a newer PHP version, or move it to a new host, and a page dies with one line: &lt;code&gt;Call to undefined function&lt;/code&gt;. The function isn't misspelled and the plugin worked yesterday. Almost every time, the code is fine and PHP is missing the extension that provides that function - every PHP version keeps its own list of enabled extensions, and the one you just switched to doesn't have it ticked. Here's how to tell which extension it is and switch it on in cPanel, usually in a couple of minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the error is telling you
&lt;/h2&gt;

&lt;p&gt;The full message names the function and the file that called it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PHP Fatal error:  Uncaught Error: Call to undefined function mb_strlen() in /home/user/public_html/wp-content/plugins/some-plugin/includes/helpers.php:42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PHP looked for &lt;code&gt;mb_strlen()&lt;/code&gt; in everything it has loaded and found nothing. There are only three ways that happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The extension that provides it is not enabled&lt;/strong&gt; for the PHP version your site runs. This is the common case, and the fix is a checkbox.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PHP itself removed the function&lt;/strong&gt; in the version you moved to - &lt;code&gt;mysql_connect()&lt;/code&gt;, &lt;code&gt;each()&lt;/code&gt;, &lt;code&gt;create_function()&lt;/code&gt; and friends. No extension brings these back; the code has to change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The function belongs to your code, not to PHP&lt;/strong&gt; - a plugin calling a helper from another plugin that is disabled, a half-uploaded file, or a typo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same problem with a class looks slightly different on PHP 8: &lt;code&gt;Class "ZipArchive" not found&lt;/code&gt; or &lt;code&gt;Class "DOMDocument" not found&lt;/code&gt;. Treat it exactly the same way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Get the exact function name from the error log
&lt;/h2&gt;

&lt;p&gt;If the page only shows a white screen or "There has been a critical error", the real line is in the log. In cPanel open &lt;strong&gt;Metrics → Errors&lt;/strong&gt;, or open the &lt;code&gt;error_log&lt;/code&gt; file in the site's folder with File Manager (see &lt;a href="https://www.getwebup.in/blog/how-to-find-and-read-error-logs-in-cpanel/" rel="noopener noreferrer"&gt;how to find and read error logs in cPanel&lt;/a&gt;). Note two things: the function or class name, and the file path - the path tells you which plugin, theme or script made the call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Match the function to its extension
&lt;/h2&gt;

&lt;p&gt;Common functions and classes, and the extension that provides each:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function or class in the error&lt;/th&gt;
&lt;th&gt;Extension to enable&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;mb_strlen()&lt;/code&gt;, &lt;code&gt;mb_substr()&lt;/code&gt;, &lt;code&gt;mb_strtolower()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;mbstring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;curl_init()&lt;/code&gt;, &lt;code&gt;curl_exec()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;curl&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;imagecreatefromjpeg()&lt;/code&gt;, &lt;code&gt;imagecreatetruecolor()&lt;/code&gt;, &lt;code&gt;imagewebp()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;gd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;mysqli_connect()&lt;/code&gt;, &lt;code&gt;new mysqli&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;mysqli (or nd_mysqli)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;new PDO('mysql:...')&lt;/code&gt; failing with "could not find driver"&lt;/td&gt;
&lt;td&gt;pdo_mysql (or nd_pdo_mysql)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;simplexml_load_string()&lt;/code&gt;, &lt;code&gt;simplexml_load_file()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;simplexml&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DOMDocument&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;dom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZipArchive&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;zip&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;idn_to_ascii()&lt;/code&gt;, &lt;code&gt;NumberFormatter&lt;/code&gt;, &lt;code&gt;grapheme_strlen()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;intl&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;bcadd()&lt;/code&gt;, &lt;code&gt;bcmul()&lt;/code&gt;, &lt;code&gt;bcdiv()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;bcmath&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;iconv()&lt;/code&gt;, &lt;code&gt;iconv_strlen()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;iconv&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;finfo_open()&lt;/code&gt;, &lt;code&gt;mime_content_type()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;fileinfo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;exif_read_data()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;exif&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;sodium_crypto_box()&lt;/code&gt; and other &lt;code&gt;sodium_*&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;sodium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Imagick&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;imagick&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SoapClient&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;soap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;apcu_fetch()&lt;/code&gt;, &lt;code&gt;apcu_store()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;apcu&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For anything not in the table, look the function up on php.net: its manual page sits under the extension that provides it. If php.net has no page for it at all, it's not a PHP function - skip to "still undefined" below. Encoded plugins that fail with a message about the ionCube Loader are a separate fix: &lt;a href="https://www.getwebup.in/blog/fix-ioncube-loader-not-installed-errors-in-cpanel/" rel="noopener noreferrer"&gt;ionCube Loader errors in cPanel&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Check what is loaded for the version your site actually runs
&lt;/h2&gt;

&lt;p&gt;This is where most people lose half an hour. Running &lt;code&gt;php -m&lt;/code&gt; over SSH lists the extensions of the &lt;em&gt;command-line&lt;/em&gt; PHP, and on cPanel that is often a different version from the one MultiPHP Manager assigns to your domain. It can show &lt;code&gt;mbstring&lt;/code&gt; while the website still fails.&lt;/p&gt;

&lt;p&gt;The reliable check is from the web side. Create a file with a random name in the site's folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="nb"&gt;phpinfo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open it in the browser. The version at the top is the one your site really uses; search the page for the extension name. &lt;strong&gt;Delete the file as soon as you're done&lt;/strong&gt; - it shows server details you don't want public.&lt;/p&gt;

&lt;p&gt;If you prefer SSH, call the PHP binary for that exact version instead of plain &lt;code&gt;php&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# CloudLinux servers (alt-php)&lt;/span&gt;
/opt/alt/php83/usr/bin/php &lt;span class="nt"&gt;-m&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; mbstring

&lt;span class="c"&gt;# Other cPanel servers (EasyApache 4)&lt;/span&gt;
/opt/cpanel/ea-php83/root/usr/bin/php &lt;span class="nt"&gt;-m&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; mbstring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Enable the extension in cPanel
&lt;/h2&gt;

&lt;h3&gt;
  
  
  If your cPanel has "Select PHP Version"
&lt;/h3&gt;

&lt;p&gt;That icon, under &lt;strong&gt;Software&lt;/strong&gt;, means the server runs CloudLinux and you can switch extensions on yourself:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Software → Select PHP Version&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Make sure the current version shown is the one your site runs (the phpinfo page from step 3 tells you).&lt;/li&gt;
&lt;li&gt;Open the &lt;strong&gt;Extensions&lt;/strong&gt; tab and tick the extension. Newer versions of this screen save as you tick; older ones have a Save button at the bottom.&lt;/li&gt;
&lt;li&gt;Reload the page that failed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two things trip people up here. First, &lt;code&gt;mysqli&lt;/code&gt; and &lt;code&gt;nd_mysqli&lt;/code&gt; (and &lt;code&gt;pdo_mysql&lt;/code&gt; and &lt;code&gt;nd_pdo_mysql&lt;/code&gt;) are two builds of the same functions against different drivers - tick one of each pair, not both, or they conflict. Second, Select PHP Version governs domains that MultiPHP Manager leaves on the server default. If MultiPHP Manager pins your domain to a specific version, the extensions for that domain come from the server's EasyApache 4 build instead, and ticking boxes here changes nothing for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  If there is no "Select PHP Version"
&lt;/h3&gt;

&lt;p&gt;Then PHP extensions are installed server-wide, as EasyApache 4 packages named like &lt;code&gt;ea-php83-php-mbstring&lt;/code&gt; or &lt;code&gt;ea-php83-php-intl&lt;/code&gt;. On shared hosting only the host can add them: open a ticket naming the extension and the PHP version, and it's normally a quick job. On your own VPS with WHM you can do it yourself under &lt;strong&gt;WHM → EasyApache 4 → Customize → PHP Extensions&lt;/strong&gt; - see &lt;a href="https://www.getwebup.in/blog/cpanel-easyapache-4-rebuild-php-apache-without-breaking-sites/" rel="noopener noreferrer"&gt;rebuilding PHP with EasyApache 4 without breaking sites&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Functions no extension can bring back
&lt;/h2&gt;

&lt;p&gt;If the function is on this list, PHP removed it. Switching an extension on won't help, because there is no extension:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Removed in&lt;/th&gt;
&lt;th&gt;Use instead&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;mysql_connect()&lt;/code&gt;, &lt;code&gt;mysql_query()&lt;/code&gt; and all &lt;code&gt;mysql_*&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;PHP 7.0&lt;/td&gt;
&lt;td&gt;mysqli or PDO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ereg()&lt;/code&gt;, &lt;code&gt;eregi()&lt;/code&gt;, &lt;code&gt;split()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;PHP 7.0&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;preg_match()&lt;/code&gt;, &lt;code&gt;preg_split()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;mcrypt_encrypt()&lt;/code&gt; and all &lt;code&gt;mcrypt_*&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;PHP 7.2&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;openssl_encrypt()&lt;/code&gt; or sodium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;each()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PHP 8.0&lt;/td&gt;
&lt;td&gt;&lt;code&gt;foreach&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;create_function()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PHP 8.0&lt;/td&gt;
&lt;td&gt;an anonymous function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;money_format()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PHP 8.0&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;NumberFormatter&lt;/code&gt; (intl)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The real fix is updating the plugin, theme or script that still calls it - its developer has almost certainly shipped a version without it. If you need the site back right now, switching the domain to its previous PHP version in MultiPHP Manager buys time; just don't stay on an end-of-life PHP. The full approach is in &lt;a href="https://www.getwebup.in/blog/how-to-change-php-version-in-cpanel-without-breaking-your-site/" rel="noopener noreferrer"&gt;changing your PHP version in cPanel without breaking your site&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  WordPress: "missing the MySQL extension"
&lt;/h2&gt;

&lt;p&gt;WordPress has its own wording for one of these. If you see&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your PHP installation appears to be missing the MySQL extension which is required by WordPress.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then the PHP version your site runs has neither &lt;code&gt;mysqli&lt;/code&gt; nor &lt;code&gt;nd_mysqli&lt;/code&gt; enabled. Tick one of them as in step 4. It usually appears right after a PHP version switch, because each version keeps its own extension list and the new one started without it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Still undefined after enabling it?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You changed a different version.&lt;/strong&gt; Recheck with phpinfo: the site may run 8.3 while you ticked the box under 8.2.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The failing code runs from cron or the command line.&lt;/strong&gt; A cron job calls a PHP binary directly, often &lt;code&gt;/usr/bin/php&lt;/code&gt; or &lt;code&gt;/usr/local/bin/php&lt;/code&gt;, which can be a different version with its own extensions. Point the cron line at the binary for your site's version, using the paths from step 3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The function is disabled, not missing.&lt;/strong&gt; Since PHP 8.0, a function listed in &lt;code&gt;disable_functions&lt;/code&gt; is removed outright, so &lt;code&gt;exec()&lt;/code&gt;, &lt;code&gt;shell_exec()&lt;/code&gt; or &lt;code&gt;proc_open()&lt;/code&gt; fail with "Call to undefined function" instead of PHP 7's "has been disabled for security reasons". Shared hosts commonly disable these. Search the phpinfo page for &lt;code&gt;disable_functions&lt;/code&gt;; if yours is listed, ask your host, or run that job somewhere you control the php.ini.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It isn't a PHP function at all.&lt;/strong&gt; Functions like &lt;code&gt;wc_get_product()&lt;/code&gt; or &lt;code&gt;get_field()&lt;/code&gt; come from plugins (WooCommerce, ACF). The error means that plugin is inactive, half-updated or loaded too late. Reinstall it and check that the plugin calling it is compatible with its current version.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What does "Call to undefined function" mean in PHP?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PHP could not find a function by that name in anything it has loaded. Usually the extension that provides it is not enabled for the PHP version the site runs; less often the function was removed from PHP, or it belongs to a plugin or library that did not load.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I enable a PHP extension in cPanel?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If cPanel has Software &amp;gt; Select PHP Version, open it, check the version matches your site, and tick the extension on the Extensions tab. Without that screen, extensions are installed server-wide through EasyApache 4, so on shared hosting you ask your host to add it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I fix "Call to undefined function mysql_connect()"?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The mysql_* functions were removed in PHP 7.0 and no extension restores them on a supported PHP version. Update the script or plugin to one that uses mysqli or PDO; switching back to an old PHP version only buys time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does my script work in the browser but fail from a cron job?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cron calls a PHP binary directly, often /usr/bin/php, which can be a different version with its own extension list. Point the cron command at the binary for the version your site uses, such as /opt/alt/php83/usr/bin/php on CloudLinux.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does exec() give "Call to undefined function" on PHP 8?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since PHP 8.0, functions listed in disable_functions are removed entirely, so calling one reports it as undefined instead of "disabled for security reasons". Check disable_functions in phpinfo(); shared hosts commonly disable exec, shell_exec and proc_open.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://www.getwebup.in/blog/php-call-to-undefined-function-enable-the-missing-extension/" rel="noopener noreferrer"&gt;Getwebup blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was created with the help of AI.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>wordpress</category>
      <category>debugging</category>
      <category>webdev</category>
    </item>
    <item>
      <title>PHP2Shell (CVE-2026-109618 and CVE-2026-109619): Check and Patch PHP in cPanel</title>
      <dc:creator>Getwebup</dc:creator>
      <pubDate>Wed, 28 Oct 2026 23:01:33 +0000</pubDate>
      <link>https://dev.to/getwebup/php2shell-cve-2026-109618-and-cve-2026-109619-check-and-patch-php-in-cpanel-3eid</link>
      <guid>https://dev.to/getwebup/php2shell-cve-2026-109618-and-cve-2026-109619-check-and-patch-php-in-cpanel-3eid</guid>
      <description>&lt;p&gt;On 21 October 2026 the PHP project shipped emergency releases for two critical vulnerabilities, CVE-2026-109618 and CVE-2026-109619 - the pair security researchers now call PHP2Shell. Both are rated 9.2 out of 10, neither needs a login, and attacks were reported from the day the fix came out. The bug is in PHP itself, not in your site: updating WordPress, a plugin or a theme does nothing for it. Here's what is affected, how to check the PHP your site really runs in cPanel, and what to do if it isn't patched.&lt;/p&gt;

&lt;h2&gt;
  
  
  What PHP2Shell is
&lt;/h2&gt;

&lt;p&gt;Two separate bugs in how PHP sets up and tears down a request:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CVE-2026-109618 - "RCE via OOM corruption".&lt;/strong&gt; If PHP runs out of memory at the wrong moment while preparing a request, internal data is left half-built, and the cleanup code afterwards treats it as valid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CVE-2026-109619 - "RCE via stale global state".&lt;/strong&gt; Data belonging to one request can survive after its memory has been freed, and the next request handled by the same PHP worker can use it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both can end in an attacker running their own code on the server. The PHP team puts the risk on "all PHP installations serving web requests": PHP-FPM, Apache mod_php, php-cgi, LiteSpeed and FrankenPHP. Apache mod_php is the most urgent, because a working exploit there fires before your application's code even runs. Researchers also showed unauthenticated reads of PHP worker memory, which can expose database passwords and API keys.&lt;/p&gt;

&lt;p&gt;On 26 October 2026 CISA &lt;a href="https://www.cisa.gov/news-events/alerts/2026/10/21/critical-vulnerabilities-php-require-immediate-patching" rel="noopener noreferrer"&gt;added both CVEs&lt;/a&gt; to its Known Exploited Vulnerabilities catalog, with 29 October as the due date for US federal civilian agencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which versions are fixed
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;PHP branch&lt;/th&gt;
&lt;th&gt;Fixed in&lt;/th&gt;
&lt;th&gt;Note&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;8.5&lt;/td&gt;
&lt;td&gt;8.5.12&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.4&lt;/td&gt;
&lt;td&gt;8.4.27&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.3&lt;/td&gt;
&lt;td&gt;8.3.36&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.2&lt;/td&gt;
&lt;td&gt;8.2.35&lt;/td&gt;
&lt;td&gt;End of life on 31 December 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.1, 8.0, 7.4&lt;/td&gt;
&lt;td&gt;No official release&lt;/td&gt;
&lt;td&gt;Minimal source backports from the PHP security team, and patched builds from hosts and distributions that usually keep the old version number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7.3 and older&lt;/td&gt;
&lt;td&gt;No fix from PHP or cPanel&lt;/td&gt;
&lt;td&gt;Some vendors (CloudLinux, Ubuntu Pro, TuxCare ELS) ship backports; otherwise upgrade to a supported branch&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 1: Check the PHP your site actually runs
&lt;/h2&gt;

&lt;p&gt;In cPanel, &lt;strong&gt;Software → MultiPHP Manager&lt;/strong&gt; shows the branch each domain uses, such as PHP 8.3. The exact patch level is the whole question here, and two quick ways show it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A temporary phpinfo page.&lt;/strong&gt; Create a file with a random name in the site's folder containing &lt;code&gt;&amp;lt;?php phpinfo();&lt;/code&gt;, open it in the browser and read the version at the top, then delete the file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The response header&lt;/strong&gt;, if your server sends it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; x-powered-by
x-powered-by: PHP/8.4.27
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't go by &lt;code&gt;php -v&lt;/code&gt; over SSH: on cPanel the command-line PHP is often a different version from the one serving the website.&lt;/p&gt;

&lt;p&gt;On 8.2 to 8.5, compare the number with the table: anything lower is unpatched, unless your host or Linux distribution backported the fix without changing the number - some do, so check their security advisory before assuming the worst. On 8.1, 8.0 or 7.4 the number can't tell you anything - a fixed 8.1 build still says 8.1.34 - so only your host can confirm it, and the lasting fix is moving to a supported branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: On shared or reseller hosting, patching is your host's job
&lt;/h2&gt;

&lt;p&gt;You can't update PHP on a shared server; the host updates the packages for everyone. What you can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ask directly:&lt;/strong&gt; "Have the PHP builds on my server been updated for CVE-2026-109618 and CVE-2026-109619, including the 7.4, 8.0 and 8.1 builds?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Move off 8.1 or older.&lt;/strong&gt; Switching the domain to 8.3 or 8.4 in MultiPHP Manager puts you on a branch that gets official fixes. Test first - see &lt;a href="https://www.getwebup.in/blog/how-to-change-php-version-in-cpanel-without-breaking-your-site/" rel="noopener noreferrer"&gt;changing your PHP version in cPanel without breaking your site&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The stopgap settings below don't help much from a cPanel account either: PHP's advisory says they must be set in the server's configuration, not through &lt;code&gt;ini_set()&lt;/code&gt; or a &lt;code&gt;.user.ini&lt;/code&gt; file, which is where account-level PHP settings usually end up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: On your own VPS or dedicated server
&lt;/h2&gt;

&lt;h3&gt;
  
  
  cPanel with EasyApache 4 (ea-php)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dnf update &lt;span class="s1"&gt;'ea-php*'&lt;/span&gt;        &lt;span class="c"&gt;# yum on older systems&lt;/span&gt;
/scripts/restartsrv_apache_php_fpm
/scripts/restartsrv_httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the plain update, not a security-only one: these packages shipped before their advisory metadata, so &lt;code&gt;--security&lt;/code&gt; updates can skip them. To confirm a build has the fix, its changelog should name both CVEs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rpm &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;--changelog&lt;/span&gt; ea-php84-php-cli | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'CVE-2026-(109618|109619)'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also update cPanel &amp;amp; WHM itself, which runs its own PHP for the cPanel interfaces and Roundcube webmail. Builds 138.0.18, 136.0.50 and 134.0.66 or later ship PHP 8.4.27 there, and 110.0.153 backports the fix to PHP 8.1.34.&lt;/p&gt;

&lt;h3&gt;
  
  
  CloudLinux (alt-php)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dnf clean all &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; dnf upgrade &lt;span class="s1"&gt;'alt-php*'&lt;/span&gt;    &lt;span class="c"&gt;# CloudLinux 8, 9 and 10&lt;/span&gt;
yum clean all &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yum update &lt;span class="s1"&gt;'alt-php*'&lt;/span&gt;     &lt;span class="c"&gt;# CloudLinux 7&lt;/span&gt;
rpm &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;--changelog&lt;/span&gt; alt-php81-common | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'CVE-2026-(109618|109619)'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the way to check the 7.4, 8.0 and 8.1 builds, whose version numbers don't change. If you added the TuxCare ELS alt-php repository (php-els), keep it enabled. If you disabled it, enable it again. On CloudLinux 10 it is the only source of alt-php versions other than 5.2. Fixed alt-php for CloudLinux 6 is not confirmed yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  LiteSpeed
&lt;/h3&gt;

&lt;p&gt;On cPanel, LiteSpeed runs sites through lsphp built from the same ea-php or alt-php packages, so the updates above cover it. Restarting LiteSpeed does not restart lsphp: since LiteSpeed 5.3, PHP runs in detached mode. Restart the lsphp processes yourself, either all at once or one by one as each is next used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pkill lsphp                                          &lt;span class="c"&gt;# all at once&lt;/span&gt;
&lt;span class="nb"&gt;touch&lt;/span&gt; /usr/local/lsws/admin/tmp/.lsphp_restart.txt   &lt;span class="c"&gt;# or one by one&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update LiteSpeed itself too - its WebAdmin console carries its own PHP binary. &lt;a href="https://docs.litespeedtech.com/lsws/changelog/" rel="noopener noreferrer"&gt;LiteSpeed's changelog&lt;/a&gt; lists the fix in 6.3.7 build 5 (22 October) and later, and in 6.4 RC2 build 3. To update to the latest 6.3.7 build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/usr/local/lsws/admin/misc/lsup.sh &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; 6.3.7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whatever the setup, &lt;strong&gt;restart every PHP worker&lt;/strong&gt; after updating. A patched package on disk does nothing for an FPM pool or lsphp process still running the old binary.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you can't patch today
&lt;/h2&gt;

&lt;p&gt;PHP's advisory lists measures that reduce exposure. In its words they "do not make an installation safe" - they buy time until the update:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;session.upload_progress.enabled = 0&lt;/code&gt; in the server's php.ini or FPM pool, then restart the workers. This closes the path the public exploit for CVE-2026-109619 uses. PHP now also suggests keeping it at 0 after you update, until its next regular release, because of a further, unlikely RCE path (CVE-2026-115560).&lt;/li&gt;
&lt;li&gt;For CVE-2026-109618: &lt;code&gt;memory_limit = -1&lt;/code&gt; set with &lt;code&gt;php_admin_value&lt;/code&gt; so applications can't override it (temporary - it removes the per-request memory cap), and a low &lt;code&gt;post_max_size&lt;/code&gt; - 8M if the site takes no uploads, 32M if it does - with &lt;code&gt;upload_max_filesize&lt;/code&gt; below it.&lt;/li&gt;
&lt;li&gt;On PHP 8.5, &lt;code&gt;fatal_error_backtraces = 0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the server runs Imunify360 with its WAF enabled: CloudLinux says rulesets 8.83 to 8.88 block the known exploit requests and the public exploit tool, so check that 8.88 or later has arrived. On LiteSpeed, blocking starts with 8.84. A request made to look like a normal upload from the site's own pages may not match, and nothing blocks the out-of-memory path of CVE-2026-109618 yet. The update is still the fix.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Was the site hit before it was patched?
&lt;/h2&gt;

&lt;p&gt;If a site ran unpatched PHP on or after 17 October - the day of the earliest exploit attempt &lt;a href="https://aws.amazon.com/blogs/security/amazon-threat-intelligence-identifies-php2shell-exploitation-prior-to-public-disclosure-in-madpot/" rel="noopener noreferrer"&gt;Amazon reported&lt;/a&gt;, four days before the fix - spend ten minutes checking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PHP files modified since 17 October: &lt;code&gt;find ~/public_html -name '*.php' -newermt 2026-10-17&lt;/code&gt;. Your own updates will show up; anything you don't recognise is worth a look.&lt;/li&gt;
&lt;li&gt;Any &lt;code&gt;.php&lt;/code&gt; file inside &lt;code&gt;wp-content/uploads&lt;/code&gt;. There should be none.&lt;/li&gt;
&lt;li&gt;New administrator accounts in WordPress, and unfamiliar entries under &lt;strong&gt;cPanel → Cron Jobs&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because worker memory could leak, change the database password, admin passwords and any API keys the site holds once PHP is patched. If you do find something, follow &lt;a href="https://www.getwebup.in/blog/wordpress-hacked-how-to-clean-up-and-recover-safely/" rel="noopener noreferrer"&gt;cleaning up a hacked WordPress site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt; &lt;a href="https://www.php.net/archive/2026.php#2026-10-21-5" rel="noopener noreferrer"&gt;PHP security advisory, 21 October 2026&lt;/a&gt;; GitHub advisories &lt;a href="https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w" rel="noopener noreferrer"&gt;GHSA-w8hw-w9fx-j79w&lt;/a&gt; and &lt;a href="https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp" rel="noopener noreferrer"&gt;GHSA-6wmf-4rv5-p3rp&lt;/a&gt;; &lt;a href="https://blog.cloudlinux.com/php-cve-2026-109618-and-cve-2026-109619" rel="noopener noreferrer"&gt;CloudLinux package status and Imunify360 protection&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What is PHP2Shell?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PHP2Shell is the name researchers gave two critical PHP vulnerabilities, CVE-2026-109618 and CVE-2026-109619, fixed on 21 October 2026. Both can let an unauthenticated attacker run code on a server through PHP-FPM, Apache mod_php, php-cgi, LiteSpeed or FrankenPHP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which PHP versions fix PHP2Shell?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP 8.1, 8.0 and 7.4 get no official release: the PHP security team published minimal source backports, and hosts and distributions ship patched builds that usually keep the old version number. PHP 7.3 and older get no fix from PHP or cPanel. Some vendors, such as CloudLinux, Ubuntu Pro and TuxCare ELS, ship backports; otherwise, upgrade.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need to update WordPress for PHP2Shell?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. The vulnerabilities are in PHP itself, so WordPress core, plugins and themes are not where the fix goes. The server's PHP has to be updated, which on shared hosting your host does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My site runs PHP 8.1 or 7.4. Is it protected?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Only if your host installed a backported build, and the version number won't show it: a fixed 8.1 build still reports 8.1.34. Ask your host, and plan to move the site to PHP 8.3 or 8.4, which receive official fixes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does turning off session.upload_progress fix PHP2Shell?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Setting session.upload_progress.enabled to 0 server-wide closes the path the public exploit for CVE-2026-109619 uses, but it does nothing for CVE-2026-109618. PHP's advisory says only the update is a complete fix. PHP now also suggests keeping it at 0 after you update, until its next regular release, because of a further, unlikely RCE path (CVE-2026-115560).&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://www.getwebup.in/blog/php2shell-cve-2026-109618-109619-check-and-patch-php-in-cpanel/" rel="noopener noreferrer"&gt;Getwebup blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was created with the help of AI.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>security</category>
      <category>linux</category>
      <category>devops</category>
    </item>
    <item>
      <title>WordPress Site Health Warnings: What to Fix and What to Skip</title>
      <dc:creator>Getwebup</dc:creator>
      <pubDate>Wed, 28 Oct 2026 18:35:23 +0000</pubDate>
      <link>https://dev.to/getwebup/wordpress-site-health-warnings-what-to-fix-and-what-to-skip-1n1m</link>
      <guid>https://dev.to/getwebup/wordpress-site-health-warnings-what-to-fix-and-what-to-skip-1n1m</guid>
      <description>&lt;p&gt;Open Tools → Site Health in any WordPress dashboard and you'll usually get a mix of green checkmarks and a handful of warnings that sound alarming but rarely explain themselves. "Your site could not complete a loopback request." "The REST API encountered an error." Most site owners either panic and start deactivating plugins at random, or ignore the screen entirely and miss a real problem. Neither is the right move. Here's what each common warning actually means on a cPanel-hosted WordPress site, and how to fix the ones worth fixing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Site Health Is Actually Checking
&lt;/h2&gt;

&lt;p&gt;Site Health runs a set of tests against your live install: can WordPress talk to itself over HTTP, is the REST API reachable, are scheduled events (wp-cron) firing, is your PHP version current, are there unused themes and plugins sitting around as an attack surface. It splits results into "Critical" and "Recommended" — the naming matters less than understanding &lt;em&gt;why&lt;/em&gt; a test failed, because a few of these will show a warning on a perfectly healthy site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Critical Issues You Should Actually Fix
&lt;/h2&gt;

&lt;h3&gt;
  
  
  "Your site could not complete a loopback request"
&lt;/h3&gt;

&lt;p&gt;A loopback request is WordPress calling its own URL from the server side — it's how cron, plugin updates, and the block editor's preview work. When this fails, it's almost always one of three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A security plugin or ModSecurity rule is blocking the server's own IP.&lt;/strong&gt; Wordfence, Sucuri, and All In One WP Security all have a habit of firewalling localhost/127.0.0.1 or the server's own outbound requests when a rule is too aggressive. Check the plugin's firewall log for a blocked request to your own domain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS isn't resolving locally.&lt;/strong&gt; If you've moved the site and the VPS or shared server still resolves the domain to an old IP internally, the loopback goes nowhere. Test it directly from cPanel Terminal or SSH:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://yourdomain.com/wp-cron.php?doing_wp_cron
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that hangs or times out, the server can't reach itself over that hostname — check &lt;code&gt;/etc/hosts&lt;/code&gt; on a VPS, or confirm the domain's A record actually points at this server.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A wildcard &lt;code&gt;.htaccess&lt;/code&gt; block or IP allowlist is too strict.&lt;/strong&gt; Rules that whitelist only office or home IPs for wp-admin will also block the server's own loopback call if they cover &lt;code&gt;wp-cron.php&lt;/code&gt; or REST routes. Scope those rules to &lt;code&gt;/wp-admin/&lt;/code&gt; only, not the whole site.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  "The REST API encountered an error"
&lt;/h3&gt;

&lt;p&gt;This one breaks the block editor, most contact forms, and some page builders. Test it directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://yourdomain.com/wp-json/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get a 403, ModSecurity or a firewall rule is the usual culprit — check &lt;code&gt;cPanel → Security → ModSecurity&lt;/code&gt; for a triggered rule ID against &lt;code&gt;/wp-json/&lt;/code&gt; and whitelist it for that path rather than disabling ModSecurity site-wide. If you get a 500 or a blank response, it's almost always a plugin hooking into &lt;code&gt;rest_api_init&lt;/code&gt; and throwing a fatal error — deactivate plugins one at a time (or use &lt;code&gt;wp plugin deactivate --all&lt;/code&gt; via WP-CLI, then reactivate individually) and re-test after each.&lt;/p&gt;

&lt;p&gt;If the response is valid JSON but permalinks are set to "Plain," switch to any pretty permalink structure under &lt;code&gt;Settings → Permalinks&lt;/code&gt; and re-save — the REST API needs rewrite rules to route correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  "WordPress.com requests to your site are being blocked"
&lt;/h3&gt;

&lt;p&gt;This warning doesn't come from WordPress itself. It's Jetpack's, and the admin notice reads in full: "WordPress.com requests to your site are being blocked, usually by a firewall or security rule. See Site Health for details and next steps." Next to it is a &lt;strong&gt;Visit Site Health&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;Jetpack's connection runs both ways: your site calls WordPress.com, and WordPress.com calls back to your site's &lt;code&gt;xmlrpc.php&lt;/code&gt; file. This notice means the call back was refused — WordPress.com reached your server and something turned it away. Site Health's Jetpack test shows the status code your site sent back, for example "WordPress.com reached your site but the request was blocked (HTTP 403)".&lt;/p&gt;

&lt;p&gt;Two things follow. The connection itself can be perfectly fine, and &lt;strong&gt;reconnecting Jetpack won't fix it&lt;/strong&gt;, because the same rule blocks the reconnect — Jetpack's own Site Health text says so. What needs fixing is whatever blocks &lt;code&gt;xmlrpc.php&lt;/code&gt;. On cPanel hosting it is almost always one of these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An XML-RPC block you added deliberately.&lt;/strong&gt; An &lt;code&gt;.htaccess&lt;/code&gt; rule, a "disable XML-RPC" plugin, or a security plugin's XML-RPC toggle — the standard defence against &lt;a href="https://www.getwebup.in/blog/disable-xml-rpc-in-wordpress-stop-brute-force-attacks/" rel="noopener noreferrer"&gt;XML-RPC brute-force attacks&lt;/a&gt;. It shuts out WordPress.com along with the attackers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A firewall in front of the site.&lt;/strong&gt; A Cloudflare WAF, rate-limiting or bot-protection rule, or a ModSecurity rule on the server, answering WordPress.com with a 403.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A server firewall on a VPS.&lt;/strong&gt; CSF or another IP firewall that has blocked one of WordPress.com's addresses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start by checking what &lt;code&gt;xmlrpc.php&lt;/code&gt; returns from outside the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; https://yourdomain.com/xmlrpc.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A reachable file answers a plain GET with &lt;code&gt;405 Method Not Allowed&lt;/code&gt; and the line "XML-RPC server accepts POST requests only." That is the healthy result. A &lt;code&gt;403&lt;/code&gt;, a Cloudflare challenge page or a redirect means something in front of WordPress is refusing it. To send a real XML-RPC call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: text/xml'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;?xml version="1.0"?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;demo.sayHello&amp;lt;/methodName&amp;gt;&amp;lt;/methodCall&amp;gt;'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://yourdomain.com/xmlrpc.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A working endpoint replies with &lt;code&gt;Hello!&lt;/code&gt; inside an XML response. If both tests pass from your computer but the warning stays, the block is aimed at WordPress.com in particular, by IP address or as a bot. Look for refused requests to &lt;code&gt;/xmlrpc.php&lt;/code&gt; in the firewall's own log: Cloudflare's security events, the ModSecurity hits in WHM (or ask your host), or your security plugin's log.&lt;/p&gt;

&lt;p&gt;Don't fix it by opening &lt;code&gt;xmlrpc.php&lt;/code&gt; to everyone again. Either let only Jetpack's IP ranges through the rule — Jetpack publishes them on its "Add Jetpack IPs to an Allowlist" support page, with a plain-text copy at &lt;code&gt;jetpack.com/ips-v4.txt&lt;/code&gt; — or keep XML-RPC on and block only the &lt;code&gt;system.multicall&lt;/code&gt; method that brute-force tools lean on. Once WordPress.com gets through, the notice clears on its own: Jetpack re-runs the check whenever you open Site Health, and once a day in the background.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Scheduled events have failed" / background updates not working
&lt;/h3&gt;

&lt;p&gt;This means wp-cron isn't firing, which means scheduled posts, plugin update checks, and backup jobs silently stop running. On low-traffic sites this is common because WordPress's default cron only fires on a page visit. Check what's actually queued:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wp cron event list &lt;span class="nt"&gt;--fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hook,next_run_relative,recurrence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If events are piling up with negative "next run" times, disable the request-triggered cron in &lt;code&gt;wp-config.php&lt;/code&gt; and replace it with a real system cron job through cPanel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DISABLE_WP_CRON'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add this in &lt;strong&gt;cPanel → Cron Jobs&lt;/strong&gt;, running every 5 minutes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-O&lt;/span&gt; - https://yourdomain.com/wp-cron.php?doing_wp_cron &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is more reliable than page-load-triggered cron and won't slow down visitor requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommended Warnings — Which Ones Actually Matter
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Warning&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;th&gt;Worth fixing?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"Not using HTTPS for all resources" (mixed content)&lt;/td&gt;
&lt;td&gt;Images, scripts, or CSS still loading over &lt;code&gt;http://&lt;/code&gt; after an SSL move&lt;/td&gt;
&lt;td&gt;Yes — run a serialized-safe search-replace: &lt;code&gt;wp search-replace 'http://yourdomain.com' 'https://yourdomain.com' --all-tables&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"You should remove inactive plugins and themes"&lt;/td&gt;
&lt;td&gt;Deactivated code still sitting on disk&lt;/td&gt;
&lt;td&gt;Yes — unused code is still a scan target for malware and a source of stale vulnerabilities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"A persistent object cache should be used"&lt;/td&gt;
&lt;td&gt;No Redis/Memcached backend configured&lt;/td&gt;
&lt;td&gt;Only if the site is busy enough to need it — skip on a low-traffic brochure site&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"PHP version is outdated"&lt;/td&gt;
&lt;td&gt;Site running EOL PHP (7.4 and earlier)&lt;/td&gt;
&lt;td&gt;Yes, always — change it in &lt;code&gt;cPanel → MultiPHP Manager&lt;/code&gt; and test the site after&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Your site has a security vulnerability" (specific plugin)&lt;/td&gt;
&lt;td&gt;A known CVE affects an installed plugin version&lt;/td&gt;
&lt;td&gt;Yes, immediately — update or remove that plugin the same day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"This plugin has not been updated in over 2 years"&lt;/td&gt;
&lt;td&gt;Abandonware flag, not necessarily broken&lt;/td&gt;
&lt;td&gt;Only investigate if it also has open security reports&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  When It's Safe to Ignore a Warning
&lt;/h2&gt;

&lt;p&gt;Some Site Health notices are noise. A shared hosting environment you don't control the server config for will sometimes flag "recommended PHP modules" that your host has intentionally left off for security reasons, or a caching-plugin conflict that Site Health can't detect correctly. If a warning has stayed the same for months, the site performs fine, and there's no matching entry in your error log, it's reasonable to leave it. The ones to never ignore are the "Critical" tab and anything mentioning a security vulnerability by name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prevention: Keep the Screen Green
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Delete inactive themes and plugins as soon as you're sure you don't need them — don't just deactivate and forget.&lt;/li&gt;
&lt;li&gt;Scope IP-restriction and security-plugin firewall rules to specific paths (&lt;code&gt;/wp-admin/&lt;/code&gt;, &lt;code&gt;/wp-login.php&lt;/code&gt;) instead of the whole domain, so they don't catch loopback and REST calls.&lt;/li&gt;
&lt;li&gt;Move wp-cron to a real system cron job on any site that gets irregular traffic.&lt;/li&gt;
&lt;li&gt;Check Site Health after every major plugin or PHP version change — it catches breakage before visitors do.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bottom Line
&lt;/h2&gt;

&lt;p&gt;Site Health isn't a scorecard to chase 100% green on — it's a diagnostic tool. Treat the Critical tab as things to fix this week, treat plugin-vulnerability warnings as fix-today, and treat the rest as context you check against your actual error logs before acting on.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why does Site Health say my site can't complete a loopback request even though the site loads fine for visitors?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Loopback requests are the server calling its own domain internally, which is a different path than a visitor's browser request. A security plugin firewall rule, a stale internal DNS resolution, or an IP-restriction rule scoped too broadly are the usual causes - test with &lt;code&gt;curl -I https://yourdomain.com/wp-cron.php?doing_wp_cron&lt;/code&gt; from SSH or cPanel Terminal to see the actual error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it safe to just ignore Site Health warnings if the site works fine?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Recommended-tab warnings like unused themes or missing object caching are often safe to leave if you understand why they're there. Critical-tab warnings and anything naming a specific plugin vulnerability should never be ignored, even if nothing looks broken yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I fix 'The REST API encountered an error' on cPanel hosting?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;curl https://yourdomain.com/wp-json/&lt;/code&gt; to see the actual response. A 403 usually means ModSecurity is blocking the request - check WHM/cPanel's ModSecurity Audit Log for the rule ID and whitelist it for that path. A 500 or blank response usually means a plugin is fatal-erroring on the &lt;code&gt;rest_api_init&lt;/code&gt; hook - deactivate plugins one at a time to isolate it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why do scheduled posts stop publishing even though wp-cron looks configured?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;WordPress's default cron only fires when someone visits the site, so low-traffic sites can miss scheduled runs entirely. Disable it with &lt;code&gt;define('DISABLE_WP_CRON', true);&lt;/code&gt; in wp-config.php and replace it with a real cPanel cron job hitting wp-cron.php every 5 minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does switching PHP versions fix the 'PHP version outdated' Site Health warning immediately?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, once you change it under cPanel's MultiPHP Manager the warning clears right away. Test the site immediately after switching, since older plugins or themes can throw fatal errors on a newer PHP version - keep a backup or staging copy ready before changing production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does "WordPress.com requests to your site are being blocked" mean?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's a Jetpack notice. WordPress.com tried to call your site's &lt;code&gt;xmlrpc.php&lt;/code&gt; file and your site refused, usually because of an XML-RPC block, a Cloudflare or ModSecurity rule, or a security plugin. Reconnecting Jetpack won't fix it. Let Jetpack's published IP ranges through the rule, or block only the &lt;code&gt;system.multicall&lt;/code&gt; method instead of all of XML-RPC, then reopen Tools → Site Health. The notice clears once WordPress.com gets through.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://www.getwebup.in/blog/wordpress-site-health-warnings-what-to-fix-and-what-to-skip/" rel="noopener noreferrer"&gt;Getwebup blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was created with the help of AI.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>php</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>MySQL max_user_connections Error: Causes and the Fix</title>
      <dc:creator>Getwebup</dc:creator>
      <pubDate>Wed, 28 Oct 2026 18:35:05 +0000</pubDate>
      <link>https://dev.to/getwebup/mysql-maxuserconnections-error-causes-and-the-fix-3mf5</link>
      <guid>https://dev.to/getwebup/mysql-maxuserconnections-error-causes-and-the-fix-3mf5</guid>
      <description>&lt;p&gt;Your site throws "Error establishing a database connection," but when you check the MySQL error log or a debug query, the real message is &lt;code&gt;ERROR 1226 (42000): User 'dbuser' has exceeded the 'max_user_connections' resource (current value: 20)&lt;/code&gt;. If that looks familiar, you're not hitting a server-wide MySQL limit — you're hitting a per-account cap, and the fix is completely different from the usual "raise max_connections" advice.&lt;/p&gt;

&lt;h2&gt;
  
  
  What max_user_connections actually is
&lt;/h2&gt;

&lt;p&gt;MySQL has two separate connection ceilings, and mixing them up wastes a lot of troubleshooting time:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Limit&lt;/th&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Who sets it&lt;/th&gt;
&lt;th&gt;Typical error&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max_connections&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Whole MySQL server, all users combined&lt;/td&gt;
&lt;td&gt;Server admin, in &lt;code&gt;my.cnf&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ERROR 1040: Too many connections&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max_user_connections&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;One specific database user only&lt;/td&gt;
&lt;td&gt;Per-account grant, or a WHM/cPanel resource limit&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ERROR 1226: User has exceeded the 'max_user_connections' resource&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On shared cPanel hosting, every account usually gets its own database user with its own cap on simultaneous connections — often somewhere between 10 and 25, depending on the plan. The rest of the server can be sitting nearly idle and you'll still get locked out the moment your site alone opens more connections than your account is allowed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading the error, word by word
&lt;/h2&gt;

&lt;p&gt;The full message usually looks like one of these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR 1226 (42000): User 'dbuser' has exceeded the 'max_user_connections' resource (current value: 80)
could not connect to the database 3306. user 'dbuser' has exceeded the 'max_user_connections' resource (current value: 80)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;1226&lt;/code&gt;&lt;/strong&gt; is MySQL's error number for a per-user resource limit being hit. It is not a password or permissions problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;user 'dbuser'&lt;/code&gt;&lt;/strong&gt; is the database user your site logs in as, from &lt;code&gt;wp-config.php&lt;/code&gt; or your app's config. Only that user is being refused; other sites on the same server keep working.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;(current value: 80)&lt;/code&gt;&lt;/strong&gt; is the limit itself, not the number of connections open right now. This user may hold at most 80 connections at once, and a new one was refused because all 80 were in use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;could not connect to the database 3306&lt;/code&gt;&lt;/strong&gt; is your application's own wording around the same MySQL error; &lt;code&gt;3306&lt;/code&gt; is simply the port MySQL listens on. The cause and the fix are the same as for the plain 1226 message.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why it happens
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Traffic burst on a low-limit plan
&lt;/h3&gt;

&lt;p&gt;A sale, a newsletter blast, or a bot crawl can spin up more concurrent PHP processes than usual. Each one opens its own MySQL connection, and on a plan capped at 15–20 connections per user, that's not much headroom. Entry-level shared hosting plans are sized for typical traffic, not spikes, precisely because most accounts on the server never come close to their cap — until one day yours does.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connections that don't close cleanly
&lt;/h3&gt;

&lt;p&gt;Persistent connections (&lt;code&gt;mysqli_connect&lt;/code&gt; with the &lt;code&gt;p:&lt;/code&gt; prefix, or some poorly written plugins) can hang around longer than they should. So can PHP-FPM workers that stay busy on a slow page and hold their DB connection the whole time. A single slow query — an unindexed WooCommerce lookup, say — can tie up a connection for seconds instead of milliseconds, and if enough requests pile up behind it, you run out of slots even though total traffic looks unremarkable in your analytics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple sites sharing one database user
&lt;/h3&gt;

&lt;p&gt;If you've pointed two or three WordPress installs at the same MySQL user to save on account limits, their connection counts stack. One site's traffic spike can lock out the others.&lt;/p&gt;

&lt;h3&gt;
  
  
  A runaway cron job or import script
&lt;/h3&gt;

&lt;p&gt;WP-CLI loops, migration scripts, or a cron job that fires every minute and doesn't release its connection properly will quietly eat your quota in the background, so the error shows up even during low traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Confirm it's really this, not the server-wide limit
&lt;/h2&gt;

&lt;p&gt;Don't guess — check. If you have SSH or Terminal access in cPanel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mysql &lt;span class="nt"&gt;-u&lt;/span&gt; your_db_user &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"SHOW VARIABLES LIKE 'max_user_connections';"&lt;/span&gt;
mysql &lt;span class="nt"&gt;-u&lt;/span&gt; your_db_user &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"SELECT COUNT(*) FROM information_schema.processlist WHERE user='your_db_user';"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the second number is sitting right at or above the first, that's your answer. On shared hosting without shell access, check &lt;strong&gt;cPanel → MySQL Databases&lt;/strong&gt; or the resource usage panel — some hosts surface the current connection count there, or you can just check the exact wording of the error your site is throwing. "max_user_connections" in the message means per-user, not server-wide.&lt;/p&gt;

&lt;h3&gt;
  
  
  See what the open connections are doing
&lt;/h3&gt;

&lt;p&gt;Knowing the count is at the limit is only half the answer. This groups the connections by what they are doing, so the pattern is obvious:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;connections&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;MAX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;longest_seconds&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processlist&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'your_db_user'&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;state&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;connections&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A database user can always see its own connections, so this also works from phpMyAdmin's SQL tab on shared hosting. If the limit is so full that even this query can't connect, run it as root on a VPS (root sees every user's connections) or retry in a few seconds.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mostly &lt;code&gt;Sleep&lt;/code&gt;, with a large &lt;code&gt;longest_seconds&lt;/code&gt;:&lt;/strong&gt; connections are opened and never closed — persistent connections, or code that doesn't close them. See "Fix what's actually eating connections" below.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mostly &lt;code&gt;Query&lt;/code&gt;, several seconds each:&lt;/strong&gt; slow queries are piling up and holding connections while they run. Find them with the &lt;a href="https://www.getwebup.in/blog/mysql-slow-query-log-find-and-fix-queries-slowing-your-site/" rel="noopener noreferrer"&gt;MySQL slow query log&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A steady count at the limit whenever traffic rises:&lt;/strong&gt; more PHP workers than the limit allows. &lt;a href="https://www.getwebup.in/blog/php-fpm-pool-tuning-fix-pm-max-children-on-a-vps/" rel="noopener noreferrer"&gt;Tune the PHP-FPM pool&lt;/a&gt; to match.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For immediate relief you can close your own idle connections with &lt;code&gt;KILL &amp;lt;id&amp;gt;;&lt;/code&gt;, taking the IDs from &lt;code&gt;SHOW PROCESSLIST;&lt;/code&gt;. That frees slots at once, but they fill up again until the cause is fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to fix it
&lt;/h2&gt;

&lt;h3&gt;
  
  
  On shared cPanel hosting (no root access)
&lt;/h3&gt;

&lt;p&gt;You can't edit &lt;code&gt;my.cnf&lt;/code&gt; here — the limit is enforced by the hosting account's resource package. Two real options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ask your host to raise the per-account MySQL connection limit.&lt;/li&gt;
&lt;li&gt;Reduce how many connections your site opens at once — see the fixes below before assuming you need a bigger limit.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  On a VPS or dedicated server with root MySQL access
&lt;/h3&gt;

&lt;p&gt;You can set the per-user limit directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="s1"&gt;'your_db_user'&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;MAX_USER_CONNECTIONS&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;FLUSH&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On older MySQL/MariaDB versions where &lt;code&gt;ALTER USER ... WITH&lt;/code&gt; isn't supported, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;USAGE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;your_database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="s1"&gt;'your_db_user'&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;MAX_USER_CONNECTIONS&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set it high enough to cover real peak traffic, but remember it's still bounded by the server-wide &lt;code&gt;max_connections&lt;/code&gt; — raising one without checking the other just moves the wall.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix what's actually eating connections
&lt;/h3&gt;

&lt;p&gt;Raising the cap buys time; it doesn't fix a leak. Check these first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PHP-FPM pool size.&lt;/strong&gt; If &lt;code&gt;pm.max_children&lt;/code&gt; in your PHP-FPM pool config is set much higher than your MySQL user's connection limit, every busy moment will hit the wall. Bring them in line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent connections.&lt;/strong&gt; If a plugin or custom code uses &lt;code&gt;mysqli_pconnect&lt;/code&gt; or PDO persistent mode, connections can sit open between requests. Turning persistent connections off usually clears this up fast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Object caching.&lt;/strong&gt; A Redis or Memcached object cache in front of WordPress cuts the number of database round-trips per page load significantly, which lowers concurrent connection pressure during traffic spikes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cron and import scripts.&lt;/strong&gt; Make sure long-running WP-CLI or migration scripts explicitly close their MySQL connection when done, and don't schedule the same heavy cron job to overlap itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prevention checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Give each site its own database user instead of sharing one across multiple installs.&lt;/li&gt;
&lt;li&gt;Match your PHP-FPM &lt;code&gt;pm.max_children&lt;/code&gt; to what your MySQL connection limit can actually support.&lt;/li&gt;
&lt;li&gt;Add an object cache (Redis or Memcached) if your site does more than a trickle of traffic.&lt;/li&gt;
&lt;li&gt;Monitor connection counts before a planned traffic event — a sale, a launch, a press mention — and ask your host to raise the limit in advance rather than mid-outage.&lt;/li&gt;
&lt;li&gt;Avoid persistent MySQL connections unless you've specifically tuned your stack for them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you keep hitting this ceiling even after cleaning up connection usage, it's usually a sign your plan's resource limits no longer match your traffic — worth a quick chat with your host before it becomes a recurring outage.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What's the difference between max_connections and max_user_connections?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;max_connections is a server-wide MySQL setting that caps total connections from every user combined. max_user_connections caps connections from one specific database user, regardless of how busy the rest of the server is. On shared cPanel hosting, you'll usually hit the per-user limit long before the server-wide one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I fix this myself on shared hosting?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can't edit the limit directly without root access, but you can reduce how many connections your site opens at once by tuning PHP-FPM, disabling persistent connections, and adding an object cache. If that's not enough, ask your host to raise the per-account limit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Will restarting MySQL fix it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It clears the immediate backlog by closing all open connections, but it's a temporary fix. If the underlying cause — a leak, an undersized limit, or an overlapping cron job — isn't addressed, the error comes back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does WordPress show a specific error for this, or just the generic database message?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;WordPress shows the same generic 'Error establishing a database connection' screen regardless of the cause. You have to check the MySQL error log, enable WP_DEBUG, or query the database directly to see the actual max_user_connections message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I know what limit my hosting plan gives me?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run SHOW VARIABLES LIKE 'max_user_connections'; against your database user if you have any command-line or phpMyAdmin SQL access. If you can't run queries, check your hosting plan's resource limits page or ask support directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does 'current value: 80' mean in the max_user_connections error?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is the limit, not the live count. The database user may hold at most 80 connections at the same time, and the error appears when one more is attempted. On shared hosting your host sets that number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does the error start with 'could not connect to the database 3306'?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That part is your application's own message, and 3306 is the port MySQL listens on. Underneath it is the same MySQL error 1226, so the cause (too many open connections for one database user) and the fix are the same.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://www.getwebup.in/blog/mysql-max-user-connections-error-causes-and-the-fix/" rel="noopener noreferrer"&gt;Getwebup blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was created with the help of AI.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>database</category>
      <category>php</category>
      <category>devops</category>
    </item>
    <item>
      <title>Cloudflare Turnstile Not Working in WordPress? Here's the Fix</title>
      <dc:creator>Getwebup</dc:creator>
      <pubDate>Wed, 28 Oct 2026 18:34:37 +0000</pubDate>
      <link>https://dev.to/getwebup/cloudflare-turnstile-not-working-in-wordpress-heres-the-fix-dk5</link>
      <guid>https://dev.to/getwebup/cloudflare-turnstile-not-working-in-wordpress-heres-the-fix-dk5</guid>
      <description>&lt;p&gt;You swapped out reCAPTCHA for Cloudflare Turnstile because it's faster, free, and doesn't track your visitors — and now the widget won't load, or it loads but every form submission comes back "verification failed." Here's how to actually fix it, not just refresh the page and hope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why site owners are moving to Turnstile
&lt;/h2&gt;

&lt;p&gt;Google reCAPTCHA works, but it ships third-party tracking cookies, occasionally shows an infinite loop of traffic-light photos to real customers, and adds a noticeable delay before your contact form is usable. Cloudflare Turnstile solves the same problem — tell bots from humans — without the cookie banner headache or the "select all the crosswalks" tax on your visitors. Most of the time it runs an invisible, non-interactive check and just passes.&lt;/p&gt;

&lt;p&gt;The catch: because it verifies the visitor's browser &lt;em&gt;and&lt;/em&gt; the exact domain it's embedded on, a handful of setup details will silently break it. Below are the most common ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Symptom 1: The widget never appears
&lt;/h2&gt;

&lt;p&gt;You add the shortcode or plugin block, save the page, and where the checkbox or Cloudflare badge should be, there's just... nothing. No error in the form, no console warning you'd notice at a glance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cause
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The Turnstile JavaScript (&lt;code&gt;https://challenges.cloudflare.com/turnstile/v0/api.js&lt;/code&gt;) is being blocked by a caching or "defer non-essential JS" plugin like WP Rocket, LiteSpeed Cache, or Autoptimize.&lt;/li&gt;
&lt;li&gt;A Content Security Policy header (set in &lt;code&gt;.htaccess&lt;/code&gt; or a security plugin) doesn't allow scripts from &lt;code&gt;challenges.cloudflare.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The site key was pasted with a stray space or line break.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open your browser's DevTools console (F12) on the page with the form. If you see a CSP violation error naming &lt;code&gt;challenges.cloudflare.com&lt;/code&gt;, that confirms cause #2.&lt;/li&gt;
&lt;li&gt;If you're using a CSP header, add this to your &lt;code&gt;script-src&lt;/code&gt; and &lt;code&gt;frame-src&lt;/code&gt; directives:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;script-src 'self' https://challenges.cloudflare.com;
frame-src 'self' https://challenges.cloudflare.com;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Exclude the Turnstile script from JS defer/delay optimisation. In WP Rocket: Settings → File Optimization → Excluded JavaScript Files, add &lt;code&gt;challenges.cloudflare.com&lt;/code&gt;. In LiteSpeed Cache: Page Optimization → JS Settings → JS Excludes.&lt;/li&gt;
&lt;li&gt;Re-copy your site key from the Cloudflare dashboard (Turnstile → your widget → Sitekey) and paste it into a plain-text editor first to strip formatting, then into your plugin settings.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Symptom 2: Widget shows, but every submission fails with "verification failed"
&lt;/h2&gt;

&lt;p&gt;The checkbox or badge renders fine. The visitor completes it (or it auto-passes). They click submit, and the form bounces back with a generic error, or the WordPress error log shows something like &lt;code&gt;cf-turnstile-response missing&lt;/code&gt; or &lt;code&gt;invalid-input-response&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cause
&lt;/h3&gt;

&lt;p&gt;This is almost always a mismatch between the &lt;strong&gt;site key&lt;/strong&gt; (public, goes in your HTML) and the &lt;strong&gt;secret key&lt;/strong&gt; (private, used server-side to verify the token with Cloudflare's API). Common ways this happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You pasted the secret key into the site key field, or vice versa — they look similar and it's an easy copy-paste mistake.&lt;/li&gt;
&lt;li&gt;You have a staging and a production Turnstile widget, and the keys got swapped during deployment.&lt;/li&gt;
&lt;li&gt;Your server can't reach Cloudflare's verification endpoint (&lt;code&gt;https://challenges.cloudflare.com/turnstile/v0/siteverify&lt;/code&gt;) — outbound HTTPS is blocked by a firewall rule, mod_security, or an aggressive VPS security group.&lt;/li&gt;
&lt;li&gt;A caching plugin is caching the form page including the one-time Turnstile token, so the visitor submits a token that already expired (tokens are valid for roughly 5 minutes and are single-use).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In the Cloudflare dashboard, go to Turnstile and confirm which key is which — the sitekey is the one you never treat as secret. Re-check both fields in your plugin.&lt;/li&gt;
&lt;li&gt;Test outbound connectivity from your server directly:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://challenges.cloudflare.com/turnstile/v0/siteverify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this times out or connection-refuses, your hosting firewall (CSF, ModSecurity, or a VPS security group) is blocking outbound HTTPS to that host. On a cPanel/CSF server, whitelist the outbound connection in &lt;code&gt;/etc/csf/csf.conf&lt;/code&gt; or ask your host to confirm outbound 443 isn't restricted.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Exclude the page containing your form from full-page caching, or at minimum exclude any URL parameter/cookie the form plugin sets. Most contact-form plugins (Contact Form 7, WPForms, Gravity Forms) already send no-cache headers on their own AJAX endpoint — check that your caching plugin isn't overriding that.&lt;/li&gt;
&lt;li&gt;If you run WooCommerce checkout or a login form behind Turnstile, make sure the widget re-renders after AJAX page updates (cart totals refresh, etc.) — a stale token from before the AJAX reload will always fail.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Symptom 3: Works on staging, fails on the live domain
&lt;/h2&gt;

&lt;p&gt;You tested everything on &lt;code&gt;staging.yoursite.com&lt;/code&gt;, it passed every time. You push to production and it breaks immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cause
&lt;/h3&gt;

&lt;p&gt;Turnstile widgets are locked to the exact hostnames you list when you create them in the Cloudflare dashboard. If your production domain, its &lt;code&gt;www&lt;/code&gt; variant, or your staging subdomain isn't in that list, verification fails with a domain mismatch — Cloudflare's API rejects it silently from the form's point of view.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;In Cloudflare → Turnstile → your widget → Settings, check the "Domains" list. Add every hostname the form is actually served from:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hostname you need to add&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;yourdomain.com&lt;/td&gt;
&lt;td&gt;Root domain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="http://www.yourdomain.com" rel="noopener noreferrer"&gt;www.yourdomain.com&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;www redirect target, if visitors land here first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;staging.yourdomain.com&lt;/td&gt;
&lt;td&gt;Staging/testing environment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;localhost / 127.0.0.1&lt;/td&gt;
&lt;td&gt;Local development — Turnstile has a dedicated toggle for this&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Changes to the domain list apply within a minute or two — no need to regenerate the keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Symptom 4: Turnstile passes, but the form still submits nothing (WPForms/CF7)
&lt;/h2&gt;

&lt;p&gt;This one isn't a Turnstile problem at all — it's a plugin integration gap. Some older versions of popular form plugins added Turnstile support after reCAPTCHA, and the field name they expect doesn't match what a hand-rolled integration sends.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Update the form plugin to the latest version — Turnstile support in Contact Form 7, WPForms, and Gravity Forms has matured a lot since first release and early versions had known bugs here.&lt;/li&gt;
&lt;li&gt;If you added Turnstile manually via a snippet, confirm the hidden field name is exactly &lt;code&gt;cf-turnstile-response&lt;/code&gt; — this is what the server-side verification call reads.&lt;/li&gt;
&lt;li&gt;Check &lt;code&gt;wp-content/debug.log&lt;/code&gt; (with &lt;code&gt;WP_DEBUG_LOG&lt;/code&gt; enabled) for a PHP notice about an undefined index — that usually points straight at the mismatched field name.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Symptom 5: "Invalid request: missing Turnstile response"
&lt;/h2&gt;

&lt;p&gt;This is a different failure from "verification failed." When the error says the Turnstile response is &lt;em&gt;missing&lt;/em&gt;, no token reached your server at all — the &lt;code&gt;cf-turnstile-response&lt;/code&gt; field was absent or empty in the submission. Cloudflare's own verification API reports the same condition as &lt;code&gt;missing-input-response&lt;/code&gt;: "Response parameter was not provided." Your keys can be perfectly correct and this will still fail, because the problem is in the browser or the form.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cause
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The widget sits outside the &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; it's meant to protect — in a popup, a separate page-builder block, or the footer. Turnstile's hidden &lt;code&gt;cf-turnstile-response&lt;/code&gt; field is only sent with a form when the widget is embedded inside that &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element; outside it, the challenge passes and the form still submits without a token.&lt;/li&gt;
&lt;li&gt;The form submits over AJAX, and the JavaScript that builds the request never adds the token. With explicit rendering you have to read it yourself with &lt;code&gt;turnstile.getResponse(widgetId)&lt;/code&gt; and include it.&lt;/li&gt;
&lt;li&gt;The visitor pressed submit before the widget had finished loading, because the Turnstile script is being delayed or deferred by an optimisation plugin (see Symptom 1).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open DevTools → Network, submit the form, and look at the request payload. No &lt;code&gt;cf-turnstile-response&lt;/code&gt; field, or an empty one, confirms it: the token never left the browser.&lt;/li&gt;
&lt;li&gt;Move the widget's container inside the &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element it protects.&lt;/li&gt;
&lt;li&gt;For AJAX or custom forms, get the token with &lt;code&gt;turnstile.getResponse(widgetId)&lt;/code&gt; and send it as &lt;code&gt;cf-turnstile-response&lt;/code&gt; alongside the other fields.&lt;/li&gt;
&lt;li&gt;Exclude &lt;code&gt;challenges.cloudflare.com&lt;/code&gt; from JS delay and defer, so the widget has rendered before anyone can submit.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Turnstile error messages, decoded
&lt;/h2&gt;

&lt;p&gt;Most people land here with an exact error string. Each one below points to a different link in the chain: the browser never produced a token, the token never reached your server, or your server sent it to Cloudflare and was told no. Find your message, then jump to the matching fix above.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error message&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"Turnstile verification failed", &lt;code&gt;turnstile_verification_failed&lt;/code&gt;, "Incorrect Turnstile response. Try the verification again."&lt;/td&gt;
&lt;td&gt;A token reached your server, your server sent it to Cloudflare's siteverify API, and Cloudflare answered &lt;code&gt;"success": false&lt;/code&gt;.&lt;/td&gt;
&lt;td&gt;Symptom 2 — a key mismatch, blocked outbound HTTPS, or an expired or reused token.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Invalid Turnstile response", &lt;code&gt;invalid-input-response&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Cloudflare received a token, but it isn't valid: malformed, expired, or issued by a different widget from the one your secret key belongs to.&lt;/td&gt;
&lt;td&gt;Symptom 2, step 1 — check that the site key and the secret key come from the same widget.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timeout-or-duplicate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The token is older than 300 seconds, or it has already been checked once. Every token is single-use.&lt;/td&gt;
&lt;td&gt;Reset the widget after a failed submit with &lt;code&gt;turnstile.reset(widgetId)&lt;/code&gt;, and make sure your code verifies each token only once.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Turnstile token missing", "Incorrect or missing Turnstile token", "The cf-turnstile-response field is required.", "Invalid request: missing Turnstile response", &lt;code&gt;missing-input-response&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;No token arrived with the form at all. The problem is in the browser or the form, not your keys.&lt;/td&gt;
&lt;td&gt;Symptom 5.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;missing-input-secret&lt;/code&gt;, &lt;code&gt;invalid-input-secret&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;The secret key in your plugin or code is empty or wrong.&lt;/td&gt;
&lt;td&gt;Symptom 2, step 1 — copy the secret key from the Cloudflare dashboard again.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Something went wrong with Turnstile", "Turnstile not initialized"&lt;/td&gt;
&lt;td&gt;The widget failed in the browser before it could produce a token: its script was blocked or delayed, or the page's domain isn't on the widget's hostname list (Cloudflare reports that one as client-side error &lt;code&gt;110200&lt;/code&gt;).&lt;/td&gt;
&lt;td&gt;Symptoms 1 and 3.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Siteverify isn't being called for this widget" (a notice in the Cloudflare dashboard)&lt;/td&gt;
&lt;td&gt;Visitors' browsers are getting tokens, but your server never checks them with siteverify. The widget is on the page, but nothing enforces it, so a bot can simply skip it.&lt;/td&gt;
&lt;td&gt;Turn on Turnstile validation for that form in your form plugin, not just the widget. In custom code, POST the token and your secret key to siteverify and reject the submission unless &lt;code&gt;success&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  What does "Turnstile verification failed" actually mean?
&lt;/h3&gt;

&lt;p&gt;Turnstile decides whether a visitor looks like a bot in the browser, before a token exists. By the time your form says "verification failed", the browser has produced a token and your server has asked Cloudflare to confirm it. So the message almost never means "this visitor is a bot". It means the confirmation step broke: the wrong secret key, a token used twice or held for more than five minutes, or a server that can't reach &lt;code&gt;challenges.cloudflare.com&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prevention checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep a copy of your site key and secret key in a password manager, labelled clearly — don't rely on remembering which is which.&lt;/li&gt;
&lt;li&gt;Add every environment's hostname to the widget's domain list before you deploy, not after something breaks.&lt;/li&gt;
&lt;li&gt;Exclude the Turnstile script and your form page from aggressive JS-delay and full-page caching from day one.&lt;/li&gt;
&lt;li&gt;After any migration (new server, new domain, cPanel-to-cPanel move), re-verify the domain list and re-test the form once DNS has cut over.&lt;/li&gt;
&lt;li&gt;If you self-host behind a VPS firewall, confirm outbound HTTPS to &lt;code&gt;challenges.cloudflare.com&lt;/code&gt; is allowed as part of your first-hour server checklist.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is Cloudflare Turnstile free to use?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes. Turnstile is free for unlimited sites and requests — you don't need to be on Cloudflare's paid plans or even proxy your DNS through Cloudflare to use it. You only need a free Cloudflare account to generate a site key and secret key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need my domain's nameservers on Cloudflare to use Turnstile?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Turnstile is a standalone product — it works on any domain, on any host, regardless of who manages your DNS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I run Turnstile and reCAPTCHA on the same site during migration?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most plugins let you configure only one CAPTCHA provider per form at a time, but you can run Turnstile on some forms and reCAPTCHA on others while you migrate. Just don't leave both scripts loading on the same form — they can conflict over the same submit button hook.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does the Turnstile checkbox stay stuck on 'verifying'?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This almost always means the browser can't reach challenges.cloudflare.com — check for an ad blocker or privacy extension blocking the request, a corporate firewall, or (server-side) an expired SSL certificate on your own domain that's breaking the page's mixed-content rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Turnstile slow down my page like reCAPTCHA sometimes does?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's noticeably lighter — Turnstile's managed challenge is designed to run invisibly in most cases and only escalates to an interactive check for suspicious traffic, so the vast majority of real visitors never see more than a brief badge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does 'Turnstile verification failed' mean?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your server sent the visitor's Turnstile token to Cloudflare to check, and Cloudflare rejected it. It is almost always a setup problem rather than a bot: the site key and secret key come from different widgets, the token was used twice or is older than five minutes, or your server can't reach challenges.cloudflare.com.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the cf-turnstile-response field?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is the hidden field Turnstile adds inside your form to carry the token to your server. 'The cf-turnstile-response field is required' means the form arrived without it, usually because the widget sits outside the form, an AJAX form didn't include it, or an optimisation plugin delayed the Turnstile script.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://www.getwebup.in/blog/cloudflare-turnstile-not-working-in-wordpress-here-s-the-fix/" rel="noopener noreferrer"&gt;Getwebup blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was created with the help of AI.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>cloudflare</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Choose a VPS in India: KVM, NVMe, Network and Location</title>
      <dc:creator>Getwebup</dc:creator>
      <pubDate>Tue, 22 Sep 2026 08:30:23 +0000</pubDate>
      <link>https://dev.to/getwebup/how-to-choose-a-vps-in-india-kvm-nvme-network-and-location-1d7p</link>
      <guid>https://dev.to/getwebup/how-to-choose-a-vps-in-india-kvm-nvme-network-and-location-1d7p</guid>
      <description>&lt;p&gt;Choosing a VPS is often reduced to one question:&lt;br&gt;
How much RAM and CPU do I get for my money?&lt;/p&gt;

&lt;p&gt;That is important, but it is not the whole story.&lt;/p&gt;

&lt;p&gt;Two VPS plans with the same 4 vCPU and 8 GB RAM can perform very differently depending on virtualization, storage, network connectivity, CPU allocation, and the physical location of the server.&lt;/p&gt;

&lt;p&gt;For developers deploying applications in India, these factors can have a significant impact on performance.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start With the Virtualization Technology&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first thing to check when choosing a VPS is the virtualization technology.&lt;/p&gt;

&lt;p&gt;KVM is a common virtualization technology used by VPS providers. It provides a virtual machine environment with strong isolation and gives users much more control over their server.&lt;/p&gt;

&lt;p&gt;A KVM VPS can be useful for developers who need to:&lt;/p&gt;

&lt;p&gt;Run Docker&lt;br&gt;
Configure custom networking&lt;br&gt;
Install Linux packages&lt;br&gt;
Host databases&lt;br&gt;
Configure firewalls&lt;br&gt;
Deploy APIs&lt;br&gt;
Run monitoring software&lt;br&gt;
Host websites and applications&lt;br&gt;
Install control panels&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;NVMe Storage Can Make a Big Difference&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;CPU and RAM usually get most of the attention when comparing VPS plans, but storage performance is also important.&lt;/p&gt;

&lt;p&gt;Applications such as MySQL, PostgreSQL, WordPress, Laravel, Node.js and Docker can perform many disk operations.&lt;/p&gt;

&lt;p&gt;NVMe SSDs use PCIe instead of the older SATA interface and can provide significantly better storage performance.&lt;/p&gt;

&lt;p&gt;When comparing VPS providers, don't just look for the word "NVMe."&lt;/p&gt;

&lt;p&gt;Also check:&lt;/p&gt;

&lt;p&gt;Storage redundancy&lt;br&gt;
RAID configuration&lt;br&gt;
IOPS&lt;br&gt;
Snapshot support&lt;br&gt;
Backup options&lt;br&gt;
Disk failure protection&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Server Location Matters&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If most of your users are located in India, server location should be one of the factors you consider.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;User → Server in India&lt;/p&gt;

&lt;p&gt;usually involves less geographic distance than:&lt;/p&gt;

&lt;p&gt;User → Server in Europe or the United States&lt;/p&gt;

&lt;p&gt;Lower network latency can be useful for applications where users frequently communicate with the server.&lt;/p&gt;

&lt;p&gt;This can be particularly important for:&lt;/p&gt;

&lt;p&gt;APIs&lt;br&gt;
SaaS applications&lt;br&gt;
E-commerce websites&lt;br&gt;
Databases&lt;br&gt;
Gaming servers&lt;br&gt;
Real-time applications&lt;/p&gt;

&lt;p&gt;However, advertised latency should not be treated as a guarantee. Network performance depends on the user's ISP, routing, congestion and other factors.&lt;/p&gt;

&lt;p&gt;The best approach is to test the server from the networks your customers actually use.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;ping YOUR_SERVER_IP&lt;/p&gt;

&lt;p&gt;You can also use:&lt;/p&gt;

&lt;p&gt;mtr -rw YOUR_SERVER_IP&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Don't Confuse Network Speed With Application Speed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You may see VPS providers advertising 1 Gbps, 5 Gbps or 10 Gbps networking.&lt;/p&gt;

&lt;p&gt;A high-speed network connection is useful, but it doesn't automatically make an application fast.&lt;/p&gt;

&lt;p&gt;Application performance also depends on:&lt;/p&gt;

&lt;p&gt;CPU performance&lt;br&gt;
RAM&lt;br&gt;
Storage I/O&lt;br&gt;
Database queries&lt;br&gt;
Web server configuration&lt;br&gt;
Application code&lt;br&gt;
Network routing&lt;br&gt;
Caching&lt;/p&gt;

&lt;p&gt;For example, a poorly optimized database query can take several seconds even when the server has a very fast network connection.&lt;/p&gt;

&lt;p&gt;The important thing is to benchmark the complete application rather than relying only on the advertised network speed.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check CPU Allocation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Another important factor is how the provider allocates CPU resources.&lt;/p&gt;

&lt;p&gt;Two VPS providers can both advertise:&lt;/p&gt;

&lt;p&gt;4 vCPU&lt;/p&gt;

&lt;p&gt;but the actual CPU performance can be different.&lt;/p&gt;

&lt;p&gt;Check whether the CPU is:&lt;/p&gt;

&lt;p&gt;Shared&lt;br&gt;
Fair-share&lt;br&gt;
Dedicated&lt;br&gt;
Pinned&lt;br&gt;
Burstable&lt;br&gt;
Subject to throttling&lt;/p&gt;

&lt;p&gt;For normal websites and applications, shared vCPU can be sufficient.&lt;/p&gt;

&lt;p&gt;CPU-intensive workloads may require more consistent CPU resources.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;p&gt;Game servers&lt;br&gt;
Large databases&lt;br&gt;
Build servers&lt;br&gt;
Video processing&lt;br&gt;
High-performance applications&lt;/p&gt;

&lt;p&gt;Therefore, don't compare VPS plans using vCPU count alone.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Compare the Complete Package&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A VPS that costs ₹500 per month isn't necessarily cheaper than one that costs ₹700.&lt;/p&gt;

&lt;p&gt;You should compare everything included in the plan.&lt;/p&gt;

&lt;p&gt;Feature What to check&lt;br&gt;
CPU vCPU count and allocation&lt;br&gt;
RAM Guaranteed or burstable&lt;br&gt;
Storage NVMe/SATA and redundancy&lt;br&gt;
Network Port speed and transfer allowance&lt;br&gt;
IPv4    Included or additional&lt;br&gt;
IPv6    Available or not&lt;br&gt;
Backups Included or extra&lt;br&gt;
Snapshots   Available or not&lt;br&gt;
DDoS protection Included or paid&lt;br&gt;
Support Support hours and channels&lt;br&gt;
Control panel   Included or additional&lt;br&gt;
Location    Physical server region&lt;br&gt;
Billing GST and invoice requirements&lt;/p&gt;

&lt;p&gt;This gives you a much better picture of the actual value of a VPS.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose the VPS Based on Your Workload&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Different applications require different resources.&lt;/p&gt;

&lt;p&gt;WordPress&lt;/p&gt;

&lt;p&gt;Prioritize:&lt;/p&gt;

&lt;p&gt;NVMe storage&lt;br&gt;
RAM&lt;br&gt;
Database performance&lt;br&gt;
Web server performance&lt;br&gt;
Caching&lt;br&gt;
Laravel or Node.js&lt;/p&gt;

&lt;p&gt;Prioritize:&lt;/p&gt;

&lt;p&gt;CPU&lt;br&gt;
RAM&lt;br&gt;
NVMe storage&lt;br&gt;
Network latency&lt;br&gt;
Process management&lt;br&gt;
MySQL or PostgreSQL&lt;/p&gt;

&lt;p&gt;Prioritize:&lt;/p&gt;

&lt;p&gt;RAM&lt;br&gt;
NVMe I/O&lt;br&gt;
CPU performance&lt;br&gt;
Backup strategy&lt;br&gt;
Docker&lt;/p&gt;

&lt;p&gt;Prioritize:&lt;/p&gt;

&lt;p&gt;KVM virtualization&lt;br&gt;
Root access&lt;br&gt;
RAM&lt;br&gt;
NVMe storage&lt;br&gt;
Network performance&lt;br&gt;
CI/CD&lt;/p&gt;

&lt;p&gt;Prioritize:&lt;/p&gt;

&lt;p&gt;CPU&lt;br&gt;
RAM&lt;br&gt;
Storage I/O&lt;br&gt;
Network bandwidth&lt;/p&gt;

&lt;p&gt;There is no single VPS configuration that is perfect for every workload.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Don't Forget Backups&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One of the most common mistakes is assuming that RAID means your data is backed up.&lt;/p&gt;

&lt;p&gt;It doesn't.&lt;/p&gt;

&lt;p&gt;RAID can help protect against certain disk failures, but it does not protect against:&lt;/p&gt;

&lt;p&gt;Accidental deletion&lt;br&gt;
Database corruption&lt;br&gt;
Application bugs&lt;br&gt;
Ransomware&lt;br&gt;
Incorrect deployments&lt;br&gt;
Administrator mistakes&lt;/p&gt;

&lt;p&gt;A production application should have a separate backup strategy.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Users
  |
  v
Web Server
  |
  +---- Application
  |
  +---- Database
  |
  +---- Backup System
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For important applications, backups should ideally be stored separately from the VPS itself.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Test Before Moving Production&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are considering moving an application to a new VPS, don't immediately migrate your production environment.&lt;/p&gt;

&lt;p&gt;Create a test environment first.&lt;/p&gt;

&lt;p&gt;Measure:&lt;/p&gt;

&lt;p&gt;CPU usage&lt;br&gt;
RAM usage&lt;br&gt;
Disk I/O&lt;br&gt;
Network latency&lt;br&gt;
TTFB&lt;br&gt;
Database query time&lt;br&gt;
Application response time&lt;br&gt;
Error rate&lt;/p&gt;

&lt;p&gt;Useful Linux commands include:&lt;/p&gt;

&lt;p&gt;uptime&lt;br&gt;
free -h&lt;br&gt;
df -h&lt;br&gt;
iostat -xz 1&lt;/p&gt;

&lt;p&gt;For network testing:&lt;/p&gt;

&lt;p&gt;mtr -rw YOUR_SERVER_IP&lt;/p&gt;

&lt;p&gt;For HTTP performance:&lt;/p&gt;

&lt;p&gt;curl -o /dev/null -s -w '%{http_code} %{time_starttransfer} %{time_total}\n' &lt;a href="https://example.com" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Real measurements are more useful than comparing marketing specifications alone.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;VPS Checklist for Indian Developers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before purchasing a VPS, check the following:&lt;/p&gt;

&lt;p&gt;KVM virtualization&lt;br&gt;
Full root access&lt;br&gt;
NVMe storage&lt;br&gt;
Transparent CPU allocation&lt;br&gt;
Sufficient RAM&lt;br&gt;
Indian network routing&lt;br&gt;
Suitable server location&lt;br&gt;
Backup options&lt;br&gt;
Snapshot support&lt;br&gt;
DDoS protection&lt;br&gt;
IPv4 availability&lt;br&gt;
IPv6 availability&lt;br&gt;
Monitoring&lt;br&gt;
API access&lt;br&gt;
Transparent pricing&lt;br&gt;
GST invoice if required&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Choosing a VPS isn't simply about finding the highest number of CPU cores or the largest amount of RAM for the lowest price.&lt;/p&gt;

&lt;p&gt;For developers in India, look at the complete infrastructure:&lt;/p&gt;

&lt;p&gt;Virtualization + CPU + RAM + NVMe storage + network + server location + backups.&lt;/p&gt;

&lt;p&gt;KVM provides a virtual machine environment with root-level control. NVMe can improve storage-heavy workloads. A server located closer to your users can reduce network latency, and a proper backup strategy protects your data when infrastructure problems or human mistakes occur.&lt;/p&gt;

&lt;p&gt;Ultimately, the best way to evaluate any VPS is to test it against your actual application and users rather than relying only on specifications listed on a pricing page.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
