WordPress 7 has outgrown PHP’s default OPcache limits. Here’s how we fixed it across a cPanel and CloudLinux fleet

A few weeks ago we had a customer site go down with a fatal error I had never seen before. Since then I’ve found the same root cause behind a handful of “random” outages across our fleet, traced it to a PHP default that hasn’t changed in over a decade, and rolled out a fix on every cPanel server we run. This is the write-up I wish had existed when I started digging.

If you run WordPress on cPanel, with or without CloudLinux, you almost certainly have the same problem. It just hasn’t bitten you yet.

The symptom

The outage that started this was a WordPress site with WPML, Elementor, Yoast and Wordfence. Every single request logged the same fatal:

PHP Fatal error: Uncaught Error: Call to undefined method WPML\Container\Container::()

Note the method name. There isn’t one. The class exists, the file on disk is intact, and php -l is happy. Running the same code from the CLI works. Only the web SAPI was broken, and opcache_reset() fixed it instantly.

That combination points to one thing: corrupted shared memory inside OPcache. Method and class names in compiled scripts live in OPcache’s interned strings buffer, and when that buffer is exhausted and OPcache has to restart itself under load, you can end up with a cached script whose string references point at nothing. The site doesn’t crash cleanly; it serves garbage until something flushes the cache.

Once I knew what to look for, I went back through the last couple of months of tickets. Several “site was down for 20 minutes, came back on its own” incidents fit the same shape: a plugin or core update recompiles a lot of files at once, the interned strings buffer fills, OPcache schedules a restart, and for a window of seconds to hours the site is broken.

The investigation

WordPress 7.0 added an OPcache section to Tools → Site Health → Info → Server. On a perfectly ordinary WP 7 site with a normal plugin stack it shows this:

Opcode cache                         Enabled
Opcode cache memory usage            75 MB of 128 MB
Opcode cache interned strings usage  100.00% of 8 MB (24 B free)
Opcode cache hit rate                95.93%

24 bytes free. That’s not “a bit tight”, that’s a buffer that’s been full for a long time and is one recompilation away from forcing a restart.

The defaults that produce this are in every stock php.ini:

opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000   ; 4000 before PHP 8.5

The 8 MB interned strings default was sized for the PHP ecosystem of 2013. WordPress core alone has roughly doubled in size since then, and a typical site loads a page builder, an SEO plugin, a security plugin and WooCommerce on top. It turns out I’m not the first person to notice: Ollie Jones, who wrote the Site Health check, opened php-src #21423 in March 2026 asking the PHP project to double memory_consumption and triple interned_strings_buffer because WordPress 6.9 and 7.0 run both caches completely full on simple sites. As of this writing the issue is still open and untriaged. Hosting providers have to fix this themselves.

Two things about OPcache internals that matter for sizing:

  1. The interned strings buffer is carved out of memory_consumption. Setting 256 / 64 leaves 192 MB for opcodes, not 256.
  2. OPcache shared memory is mmap’d and lazily committed. A 256 MB segment only consumes RAM for the pages that are actually written. Raising the ceiling costs you very little on accounts that don’t need it. The interned strings hash table is initialised upfront, but that’s small.
    On LiteSpeed with CloudLinux (our setup), each cPanel account’s lsphp process tree has its own OPcache segment, so these limits are per account, not per server. That’s good for isolation and it means the sizing question is “how big is the largest single site”, not “how big is the sum of all sites”.

What we’re changing

Across the fleet, for every PHP version that has OPcache enabled:

opcache.memory_consumption=256
opcache.interned_strings_buffer=64
opcache.max_accelerated_files=20000
opcache.max_wasted_percentage=10

Why 64 and not 32? Because we haven’t been able to measure real demand yet. A buffer reporting 100% usage tells you it’s clipped, not what the site actually wants. The plan is to set a value generous enough that nothing is clipped, measure actual usage across accounts for a day (more on that below), and then tighten if the data says 64 is wasteful. Memory-wise the difference between 32 and 64 is almost entirely unresident pages, so starting high is cheap.

max_accelerated_files is rounded up internally to the next prime from a fixed list, so 20000 becomes 32531. The hash table cost is negligible.

One important point before we get into the mechanics: PHP silently ignores INI directives for extensions that aren’t loaded. If you set opcache.* on a PHP version where OPcache isn’t installed or enabled, nothing happens. No warning, no fatal. That makes it safe to deploy these settings uniformly and let the per-version and per-user OPcache state decide whether they take effect.

Before you touch anything: audit

Every server has a different mix of PHP versions, so the first step is a read-only look at what’s actually in effect. This is the script we used. For alt-php it has to run as a real cPanel user, because the CloudLinux PHP Selector links extensions per user and root’s CLI never loads OPcache at all (the first version of our audit printed blank rows for alt-php and I briefly thought OPcache was off everywhere).

#!/bin/bash
# opcache-audit.sh — read-only. Usage: ./opcache-audit.sh [-u cpanel_user]
set -u
AUDIT_USER=""
while getopts "u:" o; do [ "$o" = u ] && AUDIT_USER=$OPTARG; done
 
q() {
  local cmd='echo ini_get("opcache.memory_consumption")," ",ini_get("opcache.interned_strings_buffer")," ",ini_get("opcache.max_accelerated_files"),"\n";'
  if [ -n "${2:-}" ]; then
    su -s /bin/bash "$2" -c "$1 -d display_errors=0 -r '$cmd'" 2>/dev/null
  else
    "$1" -d display_errors=0 -r "$cmd" 2>/dev/null
  fi
}
 
printf "%-10s %-6s %-6s %-6s\n" VERSION MEM INTERN FILES
for d in /opt/cpanel/ea-php*; do
  bin="$d/root/usr/bin/php"; [ -x "$bin" ] || continue
  read mem int files <<< "$(q "$bin")"
  printf "%-10s %-6s %-6s %-6s\n" "$(basename "$d")" "${mem:--}" "${int:--}" "${files:--}"
done
 
if [ -d /etc/cl.selector ]; then
  [ -z "$AUDIT_USER" ] && AUDIT_USER=$(grep -rls '^opcache' /home/*/.cl.selector/alt_php.ini 2>/dev/null | head -1 | cut -d/ -f3)
  echo; echo "alt-php (as user: ${AUDIT_USER:-NONE})"
  for d in /opt/alt/php[0-9]*; do
    bin="$d/usr/bin/php"; [ -x "$bin" ] || continue
    read mem int files <<< "$(q "$bin" "$AUDIT_USER")"
    printf "%-10s %-6s %-6s %-6s\n" "alt-$(basename "$d")" "${mem:--}" "${int:--}" "${files:--}"
  done
fi

On one of our servers this produced:

VERSION    MEM    INTERN FILES
ea-php56   128    8      4000
ea-php74   128    8      4000
ea-php81   128    8      4000
ea-php82   128    8      4000
ea-php83   128    8      4000
ea-php84   128    8      4000
ea-php85   128    8      10000
 
alt-php (as user: someuser)
alt-php82  128    8      10000
alt-php83  128    8      10000
alt-php84  128    8      10000
alt-php85  128    8      10000

Every version, both stacks, 128 / 8. The only thing that has moved in a decade is max_accelerated_files, which PHP 8.5 raised to 10000 and CloudLinux ships at 10000 on all alt-php builds.

EasyApache 4 / MultiPHP (ea-php)

On cPanel, each ea-php version has its own tree under /opt/cpanel/ea-phpXX/root/etc/. The WHM MultiPHP INI Editor edits php.ini in that tree. You can set the OPcache values there, one version at a time, on every server. Don’t. It doesn’t scale and it’s easy to miss a version.

Instead, use the php.d/ drop-in directory. Files there load after php.ini, in alphabetical order, and the last definition of a directive wins. cPanel documents php.d/local.ini as the file for custom settings that will survive EasyApache updates, and “local” sorts after “10-opcache”, so it overrides the stock 10-opcache.ini.

One trap worth knowing about: on ea-php56 the stock file is called opcache.ini, not 10-opcache.ini, and it contains the zend_extension=opcache.so line. If you create your own file named opcache.ini you will overwrite it and silently disable OPcache on PHP 5.6. Stick with local.ini.

for d in /opt/cpanel/ea-php*; do
  [ -d "$d/root/etc/php.d" ] || continue
  cat >> "$d/root/etc/php.d/local.ini" << 'EOF'
; fusioned opcache tuning
opcache.memory_consumption=256
opcache.interned_strings_buffer=64
opcache.max_accelerated_files=20000
opcache.max_wasted_percentage=10
EOF
done

A note on the MultiPHP INI Editor afterwards: its Basic Mode reads values from php.ini, so it will keep showing 128 and 8 even though the effective values are 256 and 64. Trust php -i, not the editor.

CloudLinux PHP Selector (alt-php)

alt-php is different in two ways. First, the extension set is per user: OPcache is only loaded for accounts where it’s ticked in the Selector. Second, there’s a single global override file that CloudLinux merges into every alt-php version:

/etc/cl.selector/global_php.ini

Directives under [Global] are applied to all alt-php builds when you run cagefsctl --setup-cl-selector. The opcache.* directives aren’t among the options users can change in the Selector UI, so nothing at the user level will override them.

[Global]
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 64
opcache.max_accelerated_files = 20000
opcache.max_wasted_percentage = 10

Then:

cagefsctl --setup-cl-selector

For users who don’t have OPcache enabled, the directives are inert (see the “silently ignored” point above). For users who do, they take effect on the next PHP process start.

Restart properly

Neither of the above restarts anything. On LiteSpeed, the OPcache shared memory segment belongs to the per-account lsphp parent process, and a graceful reload leaves existing parents running with the old segment size. You need a full restart:

/scripts/restartsrv_httpd

On Apache with PHP-FPM, restart the FPM pools for each version instead (/scripts/restartsrv_apache_php_fpm).

Verify per version afterwards:

/opt/cpanel/ea-php83/root/usr/bin/php -i | grep -E 'interned|memory_consumption'
su -s /bin/bash someuser -c '/opt/alt/php83/usr/bin/php -i' | grep -E 'interned|memory_consumption'

and check a WordPress Site Health page for the new numbers.

Conclusion

This is one of those problems that hides well. Nothing in the usual monitoring flags it, the outages look random, and the error message actively misleads you into debugging a plugin. The fix, once you know what you’re looking at, is four lines of INI in two files and a restart.

Three things I’d take away from it:

The default is not a recommendation. opcache.interned_strings_buffer=8 has survived unchanged since PHP 5.5 while the code it caches has grown several times over. If your stack looks anything like WordPress 7 plus a page builder, assume the defaults are wrong until Site Health proves otherwise.

Look at Site Health on a few of your own customers’ sites. WordPress 7 put the numbers right in front of you. If you see 100.00% of 8 MB, you have a latent outage waiting for the next plugin update to trigger it.

Deploy uniformly, let PHP sort it out. Unknown directives are ignored, so you don’t need to track which versions or which accounts have OPcache enabled. Write the settings everywhere once and move on.

We’ve raised the limits to 256 / 64 / 20000 across the fleet and are collecting real usage numbers from opcache_get_status() before deciding whether 64 is the right long-term default or generous. I’ll follow up with the data.

If you’ve seen the same blank-method fatals on your servers, or you have interned strings numbers from a large fleet of your own, I’d like to hear about it.

Fixing the AlmaLinux 9 dnf upgrade conflict on OpenVZ 7 containers (initscripts vs network-scripts)

If you’re running an AlmaLinux 9 container at an OpenVZ 7 VPS provider, there’s a good chance the very first dnf upgrade you run greets you with this:

Error:
 Problem: cannot install both initscripts-10.11.8-4.el9.x86_64 and initscripts-10.11.4-1.el9.x86_64
  - package network-scripts-10.11.4-1.el9.x86_64 requires initscripts(x86-64) = 10.11.4-1.el9, but none of the providers can be installed
  - cannot install the best update candidate for package initscripts-10.11.4-1.el9.x86_64
  - problem with installed package network-scripts-10.11.4-1.el9.x86_64
(try to add '--allowerasing' to command line to replace conflicting packages or '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)

You’ll typically run into this AlmaLinux 9 template at providers still running legacy SolusVM 1 with OpenVZ 7. I recently hit it on a freshly reinstalled container and, to make things more interesting, the template was still at 9.0, so the fix below also took the container through a full 9.0 to 9.8 jump in one go.

Here’s what’s going on, why dnf’s own suggestions are a trap in this environment, and the clean way out.

Why this happens

Red Hat removed the legacy network-scripts package from EL9. NetworkManager is the only supported way to configure networking. But OpenVZ containers use venet interfaces, and the vzctl distribution scripts that provision container IPs still write ifcfg files and drive the old network.service. NetworkManager doesn’t manage venet, so the container templates ship network-scripts anyway, pinned to the exact initscripts version they were built with. (SolusVM 1’s “Reconfigure Network” tool has the same limitation on KVM, which is why some providers carry the package on their KVM templates too.)

The moment the distro publishes a newer initscripts, the solver hits a wall: it wants to upgrade initscripts, but the installed network-scripts hard-requires the old version, and there’s no newer network-scripts in BaseOS to pair with it. Dead end.

Virtuozzo is aware of this. It’s tracked internally as PSBM-156563 and should be fixed in a future VHS release. Until then, you need a workaround.

Why you should NOT use --allowerasing

dnf helpfully suggests --allowerasing, and various knowledgebase articles echo it. On a KVM VPS with real NICs, erasing network-scripts and switching to NetworkManager is a valid path. On an OpenVZ venet container it will break your networking. There’s nothing for NetworkManager to take over: venet configuration comes from the host through the legacy scripts you just deleted. The container will come up on its next restart with no network config at all.

--skip-broken and --nobest “work” in the sense that they hold initscripts back and upgrade everything else, but you’ll trip over the same error on every future update, and you’re relying on the solver quietly skipping things rather than an explicit decision.

The fix: pull the matching network-scripts from the AlmaLinux devel repo

Here’s the part that makes a clean solution possible: AlmaLinux still builds network-scripts for EL9, it just lives in the devel repository instead of BaseOS. So instead of holding packages back, you upgrade the pair in lockstep. This workaround was shared by Virtuozzo support on the OpenVZ forum.

Step 1: find the version dnf wants for initscripts. It’s right there in the error message. In my case: 10.11.8-4.el9.

Step 2: download the matching network-scripts build:

cd /tmp
curl -O https://repo.almalinux.org/almalinux/9/devel/x86_64/os/Packages/network-scripts-10.11.8-4.el9.x86_64.rpm

If the exact filename 404s, browse the Packages directory and grab whatever network-scripts version is current; it will match the initscripts candidate in the error.

Step 3: upgrade the pair together:

dnf update ./network-scripts-10.11.8-4.el9.x86_64.rpm

dnf pulls the matching initscripts from BaseOS in the same transaction. The version pin is satisfied, nothing is erased, and your ifcfg files are untouched, so there’s zero network downtime.

Step 4: run the actual upgrade:

dnf upgrade

It now resolves cleanly, with nothing held back.

The catch: it recurs

This isn’t a one-time fix. The next time BaseOS ships a newer initscripts, the same conflict comes back, and you repeat the devel-repo dance with the then-current version. It’s a two-minute job once you know the pattern, but if you manage a fleet of these containers it’s worth documenting internally. The proper fix is coming from Virtuozzo under PSBM-156563.

Until then: never --allowerasing on venet, and let the devel repo keep your pair in sync.

Debugging a WP Toolkit scan failure: “Invalid field: auto_update”

While importing an existing WordPress installation into WP Toolkit on one of our cPanel servers, the scan failed with an error that, at first glance, made no sense:

Failed to register instance at '/home/example/public_html':
Failed to reset cache for the instance #51: Error: Invalid field: auto_update.

[error]FailedToExecuteWpCliCommand: exit status 1[/error]

The site was running WordPress 6.9.5. The server had WP-CLI 2.12.0. Both are far newer than anything that could plausibly not know about the auto_update field, which has existed since WordPress 5.5 and WP-CLI 2.5 — that’s 2020. And yet, here we were.

This post walks through the investigation, because the root cause turned out to be something that can silently affect any cPanel account, and the symptom points everywhere except the actual problem.

What the error means

During a scan, WP Toolkit runs WP-CLI commands like this against each installation it discovers:

wp plugin list --fields=name,status,update,auto_update

If WP-CLI can’t produce one of the requested columns, it errors out with Invalid field, and WP Toolkit fails to register the instance. So the question was simple: why would a current WP-CLI, against a current WordPress, refuse to produce a column it has supported for six years?

Ruling out the obvious suspects

Old WordPress core? No — wp core version reported 6.9.5.

A plugin disabling auto-updates? WP-CLI only exposes the auto_update column when the auto-update system is actually enabled for that site, so a plugin hooking automatic_updater_disabled could in theory cause this. But the error survived --skip-plugins --skip-themes, which rules out plugin and theme code entirely.

Constants or drop-ins? A quick wp eval-file diagnostic asking WordPress directly settled it:

array (
  'auto_update_enabled_plugin' => true,
  'updater_is_disabled'        => false,
  'file_mod_allowed'           => true,
  'DISALLOW_FILE_MODS'         => 'undefined',
  'AUTOMATIC_UPDATER_DISABLED' => 'undefined',
  'filter_auto_updater'        => false,
  'filter_file_mod'            => false,
)

Every gate was open. WordPress itself was perfectly happy to auto-update. The environment wasn’t the problem.

(Small CageFS aside: the diagnostic script had to live inside the user’s home directory. /tmp as root and /tmp inside the user’s cage are different filesystems, so a script dropped into /tmp as root simply doesn’t exist from the user’s point of view.)

The tell

If WordPress wasn’t hiding the field, then the command code itself had to be old — regardless of what the version string claimed. And there’s a quick way to check what the running command actually supports:

# wp help plugin list | grep auto_update
(no output)

The plugin list command in use didn’t document auto_update at all. The framework said 2.12.0, but the command behaved like something from 2020.

Root cause: a forgotten wp package install

WP-CLI supports user-installed packages under ~/.wp-cli/packages/. On this account, someone had at some point installed two of them:

# wp package list
+------------------------+----------+
| name                   | version  |
+------------------------+----------+
| wp-cli/doctor-command  | dev-main |
| wp-cli/profile-command | dev-main |
+------------------------+----------+

Harmless-looking. But packages are installed via Composer with their own dependency tree, and a look inside the vendor directory told the real story:

# ls ~/.wp-cli/packages/vendor/wp-cli/
checksum-command  core-command  cron-command  doctor-command
entity-command  extension-command  language-command  profile-command

Those old package installs had pulled in half of WP-CLI’s command suite as dependencies — including extension-command, which is what actually provides wp plugin list and wp theme list. And here’s the critical detail: anything in the packages vendor directory overrides the commands bundled in the phar.

So every wp invocation on this account — including the ones WP Toolkit’s scanner runs as the user — was loading a 2020-era plugin list implementation that predates the auto_update field. The phar itself was current; it just never got a say.

The fix

wp package uninstall seemed like the clean way out, but it failed (Composer return code 2 — it wants to reach Packagist to regenerate the autoloader, which doesn’t work from inside the cage). No matter — the packages directory is entirely disposable. It contains only optional packages and their autoloader, nothing about the sites themselves:

mv ~/.wp-cli/packages ~/.wp-cli/packages.bak

Immediately afterwards:

# wp plugin list --fields=name,status,update,auto_update
+---------------------+--------+-----------+-------------+
| name                | status | update    | auto_update |
+---------------------+--------+-----------+-------------+
| woocommerce         | active | none      | off         |
| elementor           | active | available | off         |
| ...                 |        |           |             |

A rescan in WP Toolkit registered the site cleanly.

One more footnote: the failed scans had referenced instance IDs that didn’t exist in wp-toolkit --list. That’s expected — WP Toolkit creates the instance record at the start of registration and rolls it back on failure, so failed attempts simply burn auto-increment IDs. Nothing to clean up.

Takeaways

  1. wp cli version doesn’t tell you what code your commands run. The framework version and the command implementations can diverge if packages are installed. wp help <command> shows what the running implementation actually supports.
  2. wp package install has a long tail. A package installed once for a debugging session years ago can silently pin core commands to ancient versions via its Composer dependencies — and keep them pinned through every WP-CLI upgrade since.
  3. When a tool errors on a field the whole stack should support, suspect the dispatch path, not the stack. WordPress was fine, WP-CLI was fine, WP Toolkit was fine. The problem was which code got loaded.
  4. If you manage cPanel servers: it’s worth a periodic sweep for ~/.wp-cli/packages/ directories across accounts. Any account that has one is a candidate for this exact failure mode.

Fix Munin MySQL Graphs on cPanel

If you have setup munin-node on a cPanel server it’s possible that your MySQL graphs stop updating at sometime, or don’t even generate from the beginning.

To fix, edit the following file:

/etc/munin/plugin-conf.d/cpanel.conf

And make sure that the mysql section contains the following:

[mysql*]
user root
group wheel
env.mysqladmin /usr/bin/mysqladmin
env.mysqlopts --defaults-extra-file=/root/.my.cnf

Setup WordPress CDN with Dediserve

My blog is running on a blazing fast Litespeed-powered server which is located in London, but because most of my visitors are from the US (check out this cool infographic!), I always wanted to setup CDN to speed things up for them too. A CDN can offer tremendous WordPress performance improvements and by utilizing the W3 Total Cache plugin you optimize WordPress from it’s core.
Since there wasn’t any related documentation available, Dediserve was very kind to offer me a free first month on their CDN service to test things out.

What is a CDN

A CDN is a global network of caching servers and smart DNS routing that delivers your content and media to your users from the closest possible location. The result is the fastest possible load times, better Google rankings and less load on your servers!
When US visitors view my blog, images are served from the UK, making it a long way from the visitor to the server. By implementing a CDN, edge servers located all around the world serve those images from the nearest location to the visitor. Dediserve is running on the OnApp CDN engine, and has over 60 locations all around the world at the time of writing.
Continue reading

Centova Cast: Upgrade from Trial to Monthly/Owned License

After trialing Centova Cast v2.2.6 for a few days, I decided to move on and purchase a paid monthly license. Since a new license key needed to be purchased, I started searching about a way to replace my license key on my current installation, but unfortunately I couldn’t find any clear instructions.

By combining information from a few forum posts and knowledge base articles from their website, I finally found a way to do it.

  1. Download their license key update utility
  2. Unzip the contents of the file to the root directory of your Centova Cast web files (eg. /var/www/ or /home/[username]/public_html/)
  3. Launch the script in your broswer: If Centova Cast is installed at http://radio.domain.com then you should launch http://radio.domain.com/licenseupdate.php
  4. Copy the license key of your newly purchased license from your Centova Cast Client Area and click the Update Key button.
  5. SSH to your server and run the command below:
    /home/centovacast/system/runascc/runascc exec ccmanage reissuelicense radio.domain.com

    (replace radio.domain.com with your FQDN you used when purchasing your license)

You should receive output similar to the following:

INF License reissuance forced; renewing license information (this may take a few moments) ...
OK Key updated; new renewal date: 2012-03-07 10:13:39

Your license key is now updated and you’re ready to roll. Happy streaming!

Fix Unknown table engine ‘INNODB’ error on Munin

In newer MySQL versions, if you have InnoDB disabled, Munin will fail to run giving you the following error:

root@myserver [~]# munin-run mysql_connections
DBD::mysql::st execute failed: Unknown table engine 'INNODB' at /etc/munin/plugins/mysql_connections line 958.

This is caused because the error message is changing between versions and the mysql_ plugin for munin hasn’t been updated in order to recognize it.
The fix is pretty simple, just open /usr/share/munin/plugins/mysql_ with vim on line 958 (hint: vim +958 filename) and replace as bellow.

Original code

    if ($@) {
 	        if ($@ =~ /Cannot call SHOW INNODB STATUS because skip-innodb is defined/) {
 	            $data->{_innodb_disabled} = 1;
 	            return;
 	        }
 	        die $@;

Fixed code

    if ($@) {
 	        if ($@ =~ /Unknown table engine 'INNODB'|Unknown storage engine 'innodb'|Cannot call SHOW INNODB STATUS because skip-innodb is defined/i) {
 	            $data->{_innodb_disabled} = 1;
 	            return;
 	        }
 	        die $@;

Save the file and you’re good to go 🙂

Monitoring bind/named with Munin on cPanel DNS Only

Last night I attempted to get named monitoring working with Munin on my two cPanel DNS Only boxes. Named is actually the most important service to monitor on a DNS Only box so in my opinion it should be enabled by default when you install Munin via WHM.
The whole process was actually really straightforward and the only thing I had to do was to apply a set of Debian instructions I found here, on CentOS. Here’s how you can install Munin and setup named monitoring Continue reading

iOS 5.0.1 beta fixes battery issue

[blackbirdpie url=”https://twitter.com/#!/iMZDL/status/132175470253973504″]

In a previous post I mentioned that after installing the GM (i.e. final) version of iOS 5, I’ve seen my battery life percentage drop below 20% in a matter of a few hours. Now after upgrading to beta 1 on Thursday and beta 2 yesterday, and I can confirm that the battery issue is now fixed 🙂
My iPhone 4 now easily goes over 24+ hours after a full charge with everything enabled! (3G, WiFi, Location services etc.)