Statamic is a flat-file Laravel CMS, which changes the performance story compared to a database-driven system like WordPress. Instead of SQL queries, every uncached request walks through YAML and Markdown files, parses Antlers or Blade templates, and rebuilds an in-memory index called the Stache. On a managed shared account that work happens inside a PHP worker with finite memory and CPU time, so an unoptimized Statamic site can feel sluggish even with modest traffic. The good news is that the slowness is almost entirely addressable from inside your hosting account, without touching root, SSH daemons, or server-wide configuration.

This article walks through the real sources of latency and the fixes you can apply through the Statamic control panel, cPanel Jupiter or DirectAdmin Evolution, the PHP Selector, File Manager, and .htaccess. Every step stays within the boundaries of an unprivileged hosting user.

Finding where the time actually goes

Before changing anything, confirm what is slow. A page that takes 1.8 seconds because the Stache is cold needs a different fix than one that is slow because of a large unoptimized image or a remote API call in a template. Start with your browser's Network tab: look at the Time To First Byte (TTFB) for the base HTML document. A high TTFB (over 600ms) points at server-side PHP work such as Stache rebuilds or template parsing. A fast TTFB but slow overall load points at front-end assets, which caching will not fix.

Statamic ships a debug bar you can enable temporarily. In your project, open .env through cPanel File Manager (it sits in the application root, usually ~/yourdomain/.env or one level above public_html in a proper Laravel layout) and set:

APP_DEBUG=true
DEBUGBAR_ENABLED=true

Reload a front-end page and the Debugbar reveals how many views were rendered, how long the Stache took to boot, and total request time. On a cold request you will frequently see the Stache consuming the majority of the request. Once you have your numbers, set APP_DEBUG=false again, because leaving debug on in production both slows the site and leaks sensitive paths.

Also check the application log at storage/logs/laravel.log through File Manager. Repeated warnings about memory limits, timeouts, or failed cache writes explain why pages intermittently hang. If you see Allowed memory size exhausted, the Stache is trying to build in a worker with too little memory, which you will address in the PHP section below.

Enabling Statamic static caching

The single largest win on shared hosting is Statamic's static caching, which serves fully rendered HTML and skips PHP entirely on repeat visits. Statamic offers two strategies: half measure and full measure. Half measure caches the rendered response in your configured Laravel cache store but still boots PHP; full measure writes static HTML files that the web server delivers directly through .htaccess rewrites, bypassing PHP almost completely. For a brochure or blog-style site, full measure is dramatically faster.

Open config/statamic/static_caching.php in File Manager and set the strategy:

'strategy' => 'full',

'strategies' => [
    'full' => [
        'driver' => 'file',
        'path' => public_path('static'),
    ],
],

Full measure requires rewrite rules so the server checks for a cached file before handing the request to Statamic. On LiteSpeed (which honors Apache-style directives) add this to the .htaccess inside public_html, above the standard Laravel front-controller block:

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Serve Statamic static cache when it exists
    RewriteCond %{REQUEST_METHOD} GET
    RewriteCond %{QUERY_STRING} ^$
    RewriteCond %{DOCUMENT_ROOT}/static/%{REQUEST_URI}_.html -f
    RewriteRule .* /static/%{REQUEST_URI}_.html [L]
</IfModule>

Keep this block before the existing RewriteRule ^ index.php [L] so static files win when present. Logged-in control panel sessions and POST requests skip the cache automatically because of the method and query-string conditions. You can exclude specific URLs (such as forms or search results) in the exclude array of the same config file.

Invalidation matters just as much as caching. Statamic clears the relevant static pages when you publish an entry, but you can confirm behavior under the invalidation key, defining rules per collection so editing one blog post does not needlessly flush the whole site. After deploying changes, warm the cache by running the Statamic cache commands. Without SSH you can trigger these through a cPanel or DirectAdmin Cron Job pointing at your PHP binary, for example a one-time scheduled entry:

/usr/local/bin/php ~/yourdomain/artisan statamic:static:warm

Set it to run once, confirm it populated the public/static directory, then remove or disable it. A periodic warm after your deploy workflow keeps the first visitor from paying the rebuild cost.

Stache warming, OPcache, and Redis

Even with static caching, any request that misses the cache (control panel, previews, excluded URLs) still boots the Stache. Keep the Stache fast by pre-warming it and by storing it efficiently. The command php artisan statamic:stache:warm rebuilds the index so the first dynamic request is not penalized; schedule it the same way as the static warm through the cPanel Cron Job interface after content deploys.

PHP OPcache gives free speed because it caches compiled PHP bytecode across requests, and Statamic plus Laravel load a lot of PHP files. In cPanel, open Select PHP Version (the PHP Selector), switch to the Extensions tab, and confirm opcache is enabled. In DirectAdmin the equivalent lives under PHP Selector in the user panel. You generally cannot edit server-wide OPcache ini values as an unprivileged user, but the Options tab in the PHP Selector exposes per-account tunables. Where available, raise opcache.memory_consumption and opcache.max_accelerated_files so the full Laravel codebase fits. If those keys are locked, the defaults are usually adequate once OPcache itself is on.

For values you cannot reach through the Selector, use a .user.ini file in public_html. This file lets an unprivileged user override permitted PHP settings per directory:

memory_limit = 256M
max_execution_time = 120
opcache.enable = 1
opcache.revalidate_freq = 60

Raising memory_limit to 256M resolves the Stache memory-exhaustion errors on larger sites, and the longer execution time prevents warm commands from timing out. Changes to .user.ini take effect after the file's cache TTL (often 300 seconds) or after you restart your account's PHP workers, which on LiteSpeed happens when you touch tmp/restart.txt or redeploy.

If your plan includes a per-account Redis instance (check cPanel for a Redis or Object Cache tool, or ask support for the socket path), point Laravel's cache and Stache at it for faster reads than the filesystem. In .env set CACHE_DRIVER=redis and the Redis connection details your panel provides, then set the Stache store to Redis in config/statamic/stache.php. Redis shines for the control panel and half-measure caching; for pure front-end delivery the full static cache still wins because it never touches PHP. If Redis is not offered, the default file cache on fast NVMe storage performs well.

Finally, let LiteSpeed handle the delivery layer efficiently. Confirm Brotli or Gzip compression and browser caching headers are active by adding expirations for static assets in .htaccess:

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    ExpiresByType image/webp "access plus 1 year"
</IfModule>

With full static caching serving HTML, OPcache accelerating cold PHP, a pre-warmed Stache, and compressed cacheable assets, a Statamic site on shared hosting responds in the low tens of milliseconds for cached pages. Re-run the Network tab TTFB check after each change so you can attribute the improvement to the right layer rather than guessing.