FreeScout is a Laravel application, and its performance profile follows Laravel conventions closely. Every request that is not served from cache bootstraps the framework, resolves service providers, loads configuration, reads translation files, and executes database queries against your conversations, threads, customers, and mailbox tables. On a managed shared plan this bootstrap cost is where most of the perceived slowness originates, especially once a helpdesk accumulates tens of thousands of threads and the conversation list has to paginate, count, and filter across large tables. The good news is that nearly all of the meaningful wins are available at the hosting-account level: PHP OPcache, a Redis cache and session store, LiteSpeed static handling, sensible PHP limits, and a correctly running background queue worker.
Before changing anything, establish a baseline. Open your browser developer tools (Network tab) and reload the conversations list, a single conversation, and the dashboard. Note the Time To First Byte for each. A healthy FreeScout install on LiteSpeed typically serves an authenticated conversation view in a few hundred milliseconds. If you are seeing multi-second TTFB, the cause is almost always one of four things: OPcache disabled or too small, config and route caches not compiled, a broken or synchronous queue, or Redis unavailable so the app falls back to the database or file cache. We will work through each in order, verifying with the application log at storage/logs/laravel.log and the per-domain error_log that cPanel and DirectAdmin write into your document root.
OPcache and PHP tuning through the PHP Selector
OPcache stores compiled PHP bytecode in memory so the framework's thousands of class files do not recompile on every request. On CloudLinux this is controlled per account through the PHP Selector, not a server-wide php.ini you would need root to edit. In cPanel Jupiter open Select PHP Version (or in DirectAdmin Evolution, Select PHP Version under the Extra Features group), switch to the Extensions tab, and confirm opcache is checked. FreeScout requires PHP 8.1 or newer for current releases, so set the domain to 8.1 or 8.2 first via MultiPHP Manager if it is still on an older branch.
Next open the Options tab in the same PHP Selector interface and tune these values. A large FreeScout codebase benefits from a generous accelerated file count and memory pool:
opcache.enable = 1
opcache.memory_consumption = 192
opcache.max_accelerated_files = 20000
opcache.interned_strings_buffer = 16
opcache.validate_timestamps = 1
opcache.revalidate_freq = 60
opcache.jit = disableKeep validate_timestamps enabled on shared hosting so that after an update the new code is picked up without needing a service restart you cannot perform. If your host exposes these keys only through a .user.ini file, create one in your FreeScout document root (usually public_html/.user.ini or the FreeScout install directory) with the same directives; the change applies after the FastCGI process recycles, typically within a couple of minutes. While in the Options tab, raise the values FreeScout genuinely needs for importing mailboxes and handling attachments:
memory_limit = 256M
max_execution_time = 120
post_max_size = 64M
upload_max_filesize = 64MThese are per-account ceilings, so they will not affect neighbours and require no privileged access. After saving, load a page and check phpinfo() through a temporary script, or read storage/logs/laravel.log for any "Allowed memory size" fatals that indicate the limit is still too low for a large IMAP fetch.
Config, route, and view caches inside FreeScout
Laravel recompiles configuration and route definitions on every request unless you compile them into a single cached file. FreeScout ships with an artisan console, and the maintenance actions are also exposed in the admin area so you do not need SSH. Go to Manage → System in the FreeScout AdminCP; the Tools section there lets you clear and rebuild caches. If you do have terminal access through cPanel's Terminal feature (available on many managed plans without root), run the compile commands from the install directory:
php artisan freescout:clear-cache
php artisan config:cache
php artisan route:cache
php artisan view:cacheThe config:cache and route:cache steps produce bootstrap/cache/config.php and bootstrap/cache/routes-v7.php, which remove dozens of filesystem reads per request. Rebuild these caches after every FreeScout update or after changing anything in the .env file, because a stale config cache is a common cause of settings appearing to be ignored. If a change to mailboxes or modules is not taking effect, clearing the cache first through the AdminCP is the correct diagnostic step before assuming a deeper problem.
Redis caching, sessions, and the background queue
The single largest FreeScout speedup on a busy helpdesk comes from moving cache and session storage into Redis and keeping the queue worker running. Many managed CloudLinux plans provide a per-account Redis instance; check cPanel for a Redis icon or ask whether one is provisioned. Once you have the socket path or host and port, edit the FreeScout .env file with File Manager (enable "Show Hidden Files" in the settings) and set:
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=nullIf your plan offers a Unix socket instead, set REDIS_HOST to the socket path your host documents. After saving, run php artisan config:cache again so the new connection is compiled in. Redis-backed sessions also eliminate the file locking contention that makes concurrent agent activity feel sluggish, because file-based sessions serialize requests that touch the same session file.
The queue is where FreeScout does its heavy lifting: sending outgoing email, fetching IMAP, running search indexing, and dispatching notifications. If the worker is not running, these tasks either block the web request or silently pile up, and the interface feels frozen while a reply is sent. On shared hosting you cannot install a systemd service, so use cPanel's Cron Jobs to keep the worker alive. FreeScout's documentation recommends a scheduler entry that runs every minute; add this cron pointing at your PHP binary and install path:
* * * * * /usr/local/bin/php /home/USER/freescout/artisan schedule:run >> /dev/null 2>&1The scheduler in turn manages the queue worker with a timeout, so a single per-minute cron keeps mail flowing without a long-running process your plan would kill. Confirm the path to PHP matches your selected version; on CloudLinux the alt-php binaries live under paths like /opt/alt/php82/usr/bin/php, and using the wrong one runs the queue on a different PHP version than your site. Watch storage/logs/laravel.log after adding the cron to confirm jobs are processing rather than throwing connection errors.
LiteSpeed static caching and asset delivery
LiteSpeed Web Server serves static assets far faster than routing them through PHP, and FreeScout emits a large bundle of CSS, JavaScript, and icon fonts on the first load. The framework already fingerprints these assets, so you can cache them aggressively for a long time and rely on the changed filename after each update to bust the cache. Add browser-cache and compression rules to the .htaccess in your FreeScout public directory, keeping in mind FreeScout's document root points at /public:
<IfModule LiteSpeed>
CacheLookup on
</IfModule>
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType font/woff2 "access plus 1 year"
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/css application/javascript application/json text/html
</IfModule>Do not attempt to enable LiteSpeed full-page caching for the authenticated helpdesk views. Conversation lists, dashboards, and reply forms are user-specific and change constantly, so page caching them would leak one agent's view to another or serve stale data. Restrict caching to static assets and let Redis handle the dynamic layer. If FreeScout runs behind a CDN or a reverse proxy your host provides, make sure the app knows its real scheme by setting APP_URL to the exact https origin in .env, which prevents mixed-content asset reloads that inflate load time.
Finally, keep the database lean, since query time dominates once tables are large. In phpMyAdmin, open the FreeScout database and use the SQL tab to review slow patterns, and periodically run FreeScout's built-in cleanup from Manage → System to purge old failed jobs and expired sessions. If you also run other Laravel-based scripts and want a broader reference on diagnosing framework crashes, the approach in this PHP fatal and white-screen diagnosis guide pairs well with the log-reading habits described here. Work through OPcache, compiled caches, Redis, the queue cron, and LiteSpeed static rules in that order, remeasuring TTFB after each, and the source of any remaining slowness becomes obvious.