Elgg is a full social networking engine, and that architecture behaves very differently from a brochure site under load. Every logged-in member triggers activity river queries, notification lookups, access-control checks, and plugin hooks on nearly every page. When a community grows past a few hundred active users, the symptoms that appear on shared hosting are rarely a genuine lack of capacity. They are almost always a single misconfigured subsystem consuming far more of your account's allocation than it should. Before you accept an upsell to a Cloud VPS, it is worth isolating which of the six common ceilings you are actually hitting: CPU seconds, physical memory, PHP workers (entry processes), I/O throughput, inode count, or database time.
Reading your real limits in CloudLinux before guessing
On our LiteSpeed and CloudLinux stack, your account runs inside a Lightweight Virtual Environment (LVE). That means CPU, memory, I/O, and concurrent processes are metered per account, and when you exceed a limit the server does not crash — it throttles or queues you. The visible result is a slow site, intermittent 508 (Resource Limit Reached) errors, or 503s during traffic spikes. Diagnosing Elgg starts with looking at which limit is being hit, not assuming you need more of everything.
In cPanel Jupiter, open Metrics → Resource Usage (the CloudLinux LVE dashboard). Switch to the detailed view and look at the faults column. A fault against CPU points to expensive PHP execution or unindexed database work. A fault against EP (entry processes) or NPROC means too many PHP requests are running concurrently — typical when the activity river or search is slow and requests pile up. A fault against PMEM (physical memory) points to a single heavy script, often a plugin or an import. A fault against IO or IOPS usually means the Elgg dataroot file store, session files, or logs are being hammered. In DirectAdmin Evolution the equivalent lives under Advanced Features → CPU/Memory/Concurrent Connection Usage. Note the exact resource before touching anything — this single step prevents most unnecessary plan upgrades.
Pair the LVE data with your PHP error log. Elgg writes application errors to its own log, but PHP fatals and memory exhaustion land in the per-directory error_log file in your document root. In File Manager, browse to /home/USER/public_html/ and open error_log. Lines containing Allowed memory size ... exhausted or Maximum execution time tell you precisely which script and which line triggered a PMEM or CPU fault. That mapping — a fault in the dashboard plus a matching stack line in the log — is what turns guessing into engineering.
The database and cron: where Elgg actually burns CPU
The most common Elgg bottleneck on shared hosting is the database, not the web tier. Elgg's data model stores entities, metadata, annotations, and relationships across a small number of wide tables. The activity river and access-collection joins can generate queries that scan large numbers of rows once your elgg_metadata and elgg_river tables grow. If your CPU faults spike whenever the dashboard or a group listing loads, this is the cause.
Open phpMyAdmin from cPanel, select your Elgg database, and run the slow-query style investigation you are permitted at user level — the process list and table analysis. Under the SQL tab you can run SHOW PROCESSLIST; to catch long-running queries in the act while your site is slow. Then confirm your tables are healthy and indexed by selecting the database and running ANALYZE TABLE elgg_metadata, elgg_river, elgg_entities; from the SQL tab. You cannot change global MySQL variables on shared hosting, but you can keep Elgg's own indexes intact. Elgg's upgrade routines occasionally add indexes; if a partial upgrade left them missing, the site's admin upgrade page under Administration → Upgrade re-runs those steps. Do not hand-edit indexes unless the Elgg documentation for your version prescribes it.
Cron is the second offender. Elgg relies on scheduled intervals (minute, fifteenmin, hourly, daily) to send notifications, generate the river summary, and run garbage collection. Many installs invoke every interval on a single frequent cron, which stacks heavy daily jobs on top of light minute jobs and produces sudden CPU and memory spikes. In cPanel go to Advanced → Cron Jobs and split the intervals so each runs at its natural frequency. A sane pattern for a shared account:
*/5 * * * * /usr/local/bin/php /home/USER/public_html/cron.php --interval=fiveminute
0 * * * * /usr/local/bin/php /home/USER/public_html/cron.php --interval=hourly
30 3 * * * /usr/local/bin/php /home/USER/public_html/cron.php --interval=daily
Calling PHP through the CLI binary keeps cron work out of your web worker pool, so heavy notification batches no longer compete with live visitors for entry processes. Verify the correct PHP path with your active version in MultiPHP Manager; on CloudLinux the selector path is often /usr/local/bin/ea-php82 or similar.
PHP memory, workers, and the inode trap
Elgg's page-composition model means a single request can load dozens of plugin hook handlers. If PMEM faults appear alongside memory exhausted log lines, raise PHP memory sensibly rather than blindly. On our stack you set per-account PHP limits through the MultiPHP INI Editor or a .user.ini file in your document root. Create or edit /home/USER/public_html/.user.ini:
memory_limit = 256M
max_execution_time = 60
upload_max_filesize = 32M
post_max_size = 34M
max_input_vars = 3000
Keep memory_limit at 256M rather than pushing to 512M or higher. A very high per-request limit lets one bloated request consume the memory that should serve several visitors, which converts a plugin problem into an account-wide throttle. If a specific plugin needs more than 256M to render a normal page, the fix is removing or replacing that plugin, not enlarging the ceiling.
The quietest killer of Elgg accounts is the inode limit. Elgg stores every uploaded avatar, cover image, and file-plugin attachment as multiple resized variants inside dataroot, plus per-user directory trees. A community with thousands of members and file uploads can consume hundreds of thousands of inodes even though total disk usage looks modest. Check Statistics in the cPanel sidebar for your File Usage (inode) count. If you are near the plan cap, the fastes wins are: clearing Elgg's server cache directory (Administration → Advanced → Flush the caches, then confirm the simplecache/views cache under dataroot is regenerated cleanly), pruning old session files, and removing orphaned files left by deleted users through Elgg's admin housekeeping. Enable simplecache and system cache under Administration → Advanced → Settings so CSS and JS are served as a small number of cached bundles instead of hundreds of dynamic requests — this cuts both CPU and I/O.
For static assets, add long-lived caching in .htaccess so LiteSpeed serves Elgg's cached CSS, JS, and images without invoking PHP:
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
</IfModule>
Elgg fingerprints its cached assets, so aggressive expiry is safe and dramatically reduces entry-process pressure. This same layered approach — cache first, index second, worker isolation third — mirrors the tuning we cover in our CodeIgniter performance guide and applies equally to Elgg's PHP layer.
When shared hosting genuinely runs out
After splitting cron, indexing tables, capping memory sensibly, enabling simplecache, and clearing the inode backlog, re-read the LVE dashboard for a full week. If CPU faults have dropped to near zero and pages render quickly under normal traffic, you did not have a capacity problem — you had a configuration problem, and you kept your current plan. Scale only when the numbers tell a clear story: sustained CPU faults during ordinary load despite lean queries, EP faults because genuine concurrent logged-in users routinely exceed your plan's entry-process cap, or an inode count that keeps climbing from legitimate member growth rather than cache debris. Those are the fingerprints of a site that has actually earned a larger plan or a Cloud VPS, where you gain dedicated CPU cores, higher process limits, and the ability to add Redis or a dedicated database instance. Moving before you have ruled out the fixes above simply relocates the same bottleneck to a more expensive server.