{"id":2830,"date":"2025-12-04T13:43:33","date_gmt":"2025-12-04T10:43:33","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/moodle-and-lms-hosting-performance-guide-php-database-and-caching-settings\/"},"modified":"2025-12-04T13:43:33","modified_gmt":"2025-12-04T10:43:33","slug":"moodle-and-lms-hosting-performance-guide-php-database-and-caching-settings","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/en\/moodle-and-lms-hosting-performance-guide-php-database-and-caching-settings\/","title":{"rendered":"Moodle and LMS Hosting Performance Guide: PHP, Database and Caching Settings"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><p>If you run Moodle or another PHP-based LMS, you quickly learn that raw CPU and RAM are only half the story. Two platforms with the same server specs can feel completely different: one is smooth during peak exams, the other struggles with logins, quiz attempts and reports. The missing piece is usually how PHP, the database and caching are configured on your hosting. In this guide, we will walk through the exact server-side settings we tune on Moodle workloads at dchost.com, and how you can apply the same logic on your own hosting plan, <a href=\"https:\/\/www.dchost.com\/vps\">VPS<\/a> or <a href=\"https:\/\/www.dchost.com\/dedicated-server\">dedicated server<\/a>. We will focus on practical parameters: which PHP version and FPM options matter, which MySQL\/MariaDB settings actually move the needle, and how to configure Redis or Memcached caching so that sessions and application data stay fast and reliable. Whether you are a school with 300 students or a university-scale deployment, the principles below will help you squeeze consistent, predictable performance out of your Moodle hosting.<\/p>\n<div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">\u0130&ccedil;indekiler<\/p><ul class=\"toc_list\"><li><a href=\"#Choosing_the_Right_Hosting_Architecture_for_Moodle\"><span class=\"toc_number toc_depth_1\">1<\/span> Choosing the Right Hosting Architecture for Moodle<\/a><ul><li><a href=\"#Single-server_setup_small_to_medium_Moodle_sites\"><span class=\"toc_number toc_depth_2\">1.1<\/span> Single-server setup (small to medium Moodle sites)<\/a><\/li><li><a href=\"#Separated_database_and_cache_growing_Moodle_deployments\"><span class=\"toc_number toc_depth_2\">1.2<\/span> Separated database and cache (growing Moodle deployments)<\/a><\/li><li><a href=\"#High-availability_and_clustering_large_universities_and_public_LMS\"><span class=\"toc_number toc_depth_2\">1.3<\/span> High-availability and clustering (large universities and public LMS)<\/a><\/li><\/ul><\/li><li><a href=\"#PHP_Settings_That_Make_Moodle_Feel_Fast\"><span class=\"toc_number toc_depth_1\">2<\/span> PHP Settings That Make Moodle Feel Fast<\/a><ul><li><a href=\"#Use_a_modern_PHP_version_and_FPM\"><span class=\"toc_number toc_depth_2\">2.1<\/span> Use a modern PHP version and FPM<\/a><\/li><li><a href=\"#Key_PHPini_limits_for_Moodle\"><span class=\"toc_number toc_depth_2\">2.2<\/span> Key PHP.ini limits for Moodle<\/a><\/li><li><a href=\"#PHP-FPM_pool_tuning\"><span class=\"toc_number toc_depth_2\">2.3<\/span> PHP-FPM pool tuning<\/a><\/li><li><a href=\"#Enable_and_tune_OPcache\"><span class=\"toc_number toc_depth_2\">2.4<\/span> Enable and tune OPcache<\/a><\/li><\/ul><\/li><li><a href=\"#Database_Configuration_for_Moodle_MySQLMariaDB_Tuning\"><span class=\"toc_number toc_depth_1\">3<\/span> Database Configuration for Moodle: MySQL\/MariaDB Tuning<\/a><ul><li><a href=\"#Core_InnoDB_settings\"><span class=\"toc_number toc_depth_2\">3.1<\/span> Core InnoDB settings<\/a><\/li><li><a href=\"#Connection_and_thread_settings\"><span class=\"toc_number toc_depth_2\">3.2<\/span> Connection and thread settings<\/a><\/li><li><a href=\"#Disable_old_query_cache_and_use_proper_indexes\"><span class=\"toc_number toc_depth_2\">3.3<\/span> Disable old query cache and use proper indexes<\/a><\/li><li><a href=\"#Storage_and_IO_considerations\"><span class=\"toc_number toc_depth_2\">3.4<\/span> Storage and I\/O considerations<\/a><\/li><\/ul><\/li><li><a href=\"#Caching_Strategy_for_Moodle_Sessions_Application_Cache_and_Reverse_Proxy\"><span class=\"toc_number toc_depth_1\">4<\/span> Caching Strategy for Moodle: Sessions, Application Cache and Reverse Proxy<\/a><ul><li><a href=\"#Separate_session_storage_from_database\"><span class=\"toc_number toc_depth_2\">4.1<\/span> Separate session storage from database<\/a><\/li><li><a href=\"#Configuring_Redis_for_Moodle\"><span class=\"toc_number toc_depth_2\">4.2<\/span> Configuring Redis for Moodle<\/a><\/li><li><a href=\"#Moodles_internal_cache_definitions\"><span class=\"toc_number toc_depth_2\">4.3<\/span> Moodle\u2019s internal cache definitions<\/a><\/li><li><a href=\"#Reverse_proxy_and_microcaching\"><span class=\"toc_number toc_depth_2\">4.4<\/span> Reverse proxy and microcaching<\/a><\/li><\/ul><\/li><li><a href=\"#Web_Server_and_PHPDB_Interaction_Details\"><span class=\"toc_number toc_depth_1\">5<\/span> Web Server and PHP\u2013DB Interaction Details<\/a><ul><li><a href=\"#Keep-Alive_and_connection_reuse\"><span class=\"toc_number toc_depth_2\">5.1<\/span> Keep-Alive and connection reuse<\/a><\/li><li><a href=\"#Static_content_offload_and_compression\"><span class=\"toc_number toc_depth_2\">5.2<\/span> Static content offload and compression<\/a><\/li><li><a href=\"#Cron_and_scheduled_tasks\"><span class=\"toc_number toc_depth_2\">5.3<\/span> Cron and scheduled tasks<\/a><\/li><\/ul><\/li><li><a href=\"#Monitoring_Capacity_Planning_and_Practical_Checklists\"><span class=\"toc_number toc_depth_1\">6<\/span> Monitoring, Capacity Planning and Practical Checklists<\/a><ul><li><a href=\"#Key_metrics_to_watch\"><span class=\"toc_number toc_depth_2\">6.1<\/span> Key metrics to watch<\/a><\/li><li><a href=\"#Practical_preexam_checklist\"><span class=\"toc_number toc_depth_2\">6.2<\/span> Practical pre\u2011exam checklist<\/a><\/li><\/ul><\/li><li><a href=\"#Bringing_It_All_Together_A_Calm_Path_to_a_Fast_Moodle\"><span class=\"toc_number toc_depth_1\">7<\/span> Bringing It All Together: A Calm Path to a Fast Moodle<\/a><\/li><\/ul><\/div>\n<h2><span id=\"Choosing_the_Right_Hosting_Architecture_for_Moodle\">Choosing the Right Hosting Architecture for Moodle<\/span><\/h2>\n<p>Before you touch any PHP or database setting, it helps to be clear about your hosting architecture. Moodle can technically run on very small shared hosting accounts, but its performance profile is closer to a serious web application than a simple brochure site.<\/p>\n<h3><span id=\"Single-server_setup_small_to_medium_Moodle_sites\">Single-server setup (small to medium Moodle sites)<\/span><\/h3>\n<p>For smaller institutions, training portals or corporate LMS deployments with up to a few hundred concurrent users, a single server is usually enough:<\/p>\n<ul>\n<li>Web server (Apache or Nginx)<\/li>\n<li>PHP-FPM<\/li>\n<li>MySQL\/MariaDB database<\/li>\n<li>Redis or Memcached for sessions and caches (optional but strongly recommended)<\/li>\n<\/ul>\n<p>In this model, all services run on one VPS or dedicated server. Performance depends heavily on good PHP-FPM tuning, a correctly sized database buffer pool and fast storage (preferably NVMe). If you are comparing storage options, our <a href=\"https:\/\/www.dchost.com\/blog\/en\/nvme-vps-hosting-rehberi-hizin-nereden-geldigini-nasil-olculdugunu-ve-gercek-sonuclari-beraber-gorelim\/\">NVMe VPS hosting guide explaining where speed really comes from<\/a> is a good background read.<\/p>\n<h3><span id=\"Separated_database_and_cache_growing_Moodle_deployments\">Separated database and cache (growing Moodle deployments)<\/span><\/h3>\n<p>Once you move beyond a few hundred concurrent learners, or run many parallel quizzes and exams, database contention becomes a bottleneck. At that point, separating services starts to pay off:<\/p>\n<ul>\n<li>One server for web + PHP-FPM<\/li>\n<li>One server for MySQL\/MariaDB<\/li>\n<li>Optional: a separate server for Redis\/Memcached<\/li>\n<\/ul>\n<p>This mirrors the architectures we describe for other heavy PHP apps, such as in our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/veritabani-sunucusunu-uygulama-sunucusundan-ayirmak-ne-zaman-mantikli\/\">when it makes sense to separate database and application servers<\/a>. Moodle benefits in similar ways: fewer context switches, better use of RAM for InnoDB caches, and clearer capacity planning for each layer.<\/p>\n<h3><span id=\"High-availability_and_clustering_large_universities_and_public_LMS\">High-availability and clustering (large universities and public LMS)<\/span><\/h3>\n<p>For multi-thousand concurrent users and mission-critical LMS portals, you may eventually move to:<\/p>\n<ul>\n<li>Multiple web + PHP nodes behind a load balancer<\/li>\n<li>A replicated or clustered database (e.g. primary\/replica)<\/li>\n<li>Highly-available Redis cluster for sessions and application cache<\/li>\n<\/ul>\n<p>The tuning concepts in this guide still apply; you just apply them per node or per cluster. If you are estimating CPU, RAM and disk throughput, the methodology we explain in <a href=\"https:\/\/www.dchost.com\/blog\/en\/woocommerce-laravel-ve-node-jsde-dogru-vps-kaynaklarini-nasil-secersin-cpu-ram-nvme-ve-bant-genisligi-rehberi\/\">how we choose VPS specs for PHP apps like WooCommerce and Laravel<\/a> also works very well for Moodle.<\/p>\n<h2><span id=\"PHP_Settings_That_Make_Moodle_Feel_Fast\">PHP Settings That Make Moodle Feel Fast<\/span><\/h2>\n<p>Moodle is written in PHP and is relatively heavy: many files, lots of database queries and often complex plugins. Optimising PHP execution is one of the easiest wins.<\/p>\n<h3><span id=\"Use_a_modern_PHP_version_and_FPM\">Use a modern PHP version and FPM<\/span><\/h3>\n<p>Moodle core keeps improving its support for newer PHP versions. As of recent releases, PHP 8.x is typically recommended. Newer versions bring:<\/p>\n<ul>\n<li>Better performance: each request uses fewer CPU cycles<\/li>\n<li>Improved type checking and error reporting, which helps stability<\/li>\n<li>New language features that some plugins may rely on<\/li>\n<\/ul>\n<p>On the hosting side we almost always run Moodle with PHP-FPM instead of old-style mod_php. PHP-FPM lets you tune worker pools per site and isolate noisy tenants. If you want a deeper dive into PHP 8.x and FPM pool tuning, our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/php-8-x-yukseltme-kontrol-listesi-wordpress-ve-laravelde-geriye-uyumluluk-opcache-preload-ve-fpm-havuz-ayarlari-nasil-tatli-tatli-kurulur\/\">the PHP 8.x upgrade checklist and FPM pool settings<\/a> lays out patterns you can adapt for Moodle.<\/p>\n<h3><span id=\"Key_PHPini_limits_for_Moodle\">Key PHP.ini limits for Moodle<\/span><\/h3>\n<p>Moodle deals with large file uploads (assignments, SCORM packages, videos), long-running scripts (backups, reports) and plenty of form submissions. Review at least these settings:<\/p>\n<ul>\n<li><strong>memory_limit<\/strong>: For production Moodle, 256M is usually a minimum; 512M is safer for large sites or heavy plugins. Monitor PHP fatal errors in logs to check if you hit the limit.<\/li>\n<li><strong>upload_max_filesize<\/strong> and <strong>post_max_size<\/strong>: Set these to accommodate your largest expected file uploads (e.g. 64M, 128M, 512M). Remember <strong>post_max_size<\/strong> must be \u2265 <strong>upload_max_filesize<\/strong>.<\/li>\n<li><strong>max_execution_time<\/strong>: For interactive pages, 60 seconds is enough. For CLI cron and scheduled tasks, you can use a higher value (or rely on CLI defaults).<\/li>\n<li><strong>max_input_vars<\/strong>: Some Moodle forms post thousands of variables (question banks, permissions). 1000 (the default) can be too low; values like 3000\u20135000 are common on busy sites.<\/li>\n<\/ul>\n<h3><span id=\"PHP-FPM_pool_tuning\">PHP-FPM pool tuning<\/span><\/h3>\n<p>On a dedicated or VPS server with only Moodle, using <strong>pm = dynamic<\/strong> works well. For example, on a 4 vCPU \/ 8 GB RAM server:<\/p>\n<ul>\n<li><strong>pm.max_children<\/strong>: 20\u201330 as a starting point<\/li>\n<li><strong>pm.start_servers<\/strong>: 4\u20136<\/li>\n<li><strong>pm.min_spare_servers<\/strong>: 4<\/li>\n<li><strong>pm.max_spare_servers<\/strong>: 10<\/li>\n<\/ul>\n<p>The right numbers depend on your average PHP memory usage per request. A common technique is:<\/p>\n<ol>\n<li>Check average RSS memory of php-fpm processes under load (using tools like <code>top<\/code> or <code>ps<\/code>).<\/li>\n<li>Reserve some RAM for the OS, database and caches.<\/li>\n<li>Divide the remaining RAM by average PHP process size to estimate a safe <strong>pm.max_children<\/strong>.<\/li>\n<\/ol>\n<p>If PHP-FPM processes are constantly at their max and new connections queue up, users will feel slowness during peak hours, even if CPU isn\u2019t fully used.<\/p>\n<h3><span id=\"Enable_and_tune_OPcache\">Enable and tune OPcache<\/span><\/h3>\n<p>Moodle\u2019s codebase is large; without OPcache, PHP re-parses hundreds of files on each request. OPcache is mandatory for serious Moodle performance. Typical settings:<\/p>\n<ul>\n<li><strong>opcache.enable = 1<\/strong> and <strong>opcache.enable_cli = 1<\/strong><\/li>\n<li><strong>opcache.memory_consumption<\/strong>: 256\u2013512 MB for large Moodle instances with many plugins<\/li>\n<li><strong>opcache.max_accelerated_files<\/strong>: 20000\u201340000 depending on plugin count<\/li>\n<li><strong>opcache.validate_timestamps<\/strong>: 1 in development, can be 0 in production if you clear OPcache on deploy<\/li>\n<\/ul>\n<p>When OPcache is too small, it starts evicting scripts and Moodle feels randomly slow under load. Monitoring OPcache hit rates and restart counts can quickly reveal undersizing.<\/p>\n<h2><span id=\"Database_Configuration_for_Moodle_MySQLMariaDB_Tuning\">Database Configuration for Moodle: MySQL\/MariaDB Tuning<\/span><\/h2>\n<p>Most Moodle installations run on MySQL or MariaDB. Moodle is write-heavy (logs, quiz attempts, tracking) and benefits a lot from InnoDB tuning. The database layer is often the biggest performance gain after PHP caching.<\/p>\n<h3><span id=\"Core_InnoDB_settings\">Core InnoDB settings<\/span><\/h3>\n<p>On a dedicated database server (or a VPS where MySQL is the main service), start by sizing the InnoDB buffer pool correctly:<\/p>\n<ul>\n<li><strong>innodb_buffer_pool_size<\/strong>: 50\u201370% of total RAM on a database-only server, or less if the database shares RAM with PHP and other services.<\/li>\n<li><strong>innodb_buffer_pool_instances<\/strong>: 1 for small pools (&lt; 1 GB), 2\u20138 for larger pools to reduce contention.<\/li>\n<li><strong>innodb_log_file_size<\/strong>: Larger files (512M\u20132G) reduce checkpoints for write-heavy workloads like Moodle logging, but must be balanced with recovery time.<\/li>\n<\/ul>\n<p>We use very similar principles when tuning e-commerce databases; you can see that approach in our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/woocommerce-icin-mysql-innodb-tuning-kontrol-listesi-buffer-pool-indeksleme-ve-slow-query-analizi-nasil-akillica-yapilir\/\">MySQL\/InnoDB tuning for WooCommerce<\/a>. The queries differ, but the idea is the same: keep hot data in RAM and avoid disk thrashing.<\/p>\n<h3><span id=\"Connection_and_thread_settings\">Connection and thread settings<\/span><\/h3>\n<p>Moodle can use many concurrent PHP workers, and therefore many database connections. Poorly tuned connection limits mean either lockups (too many threads) or errors (too few connections).<\/p>\n<ul>\n<li><strong>max_connections<\/strong>: Set just above your maximum expected concurrent PHP-FPM children across all web servers. For a single node with 30 children, 100\u2013150 is a safe value.<\/li>\n<li><strong>thread_cache_size<\/strong>: 50\u2013100 to reuse threads instead of creating new ones for each connection.<\/li>\n<li><strong>wait_timeout<\/strong>: Reduce from default (often 28800s) to something like 300\u2013600s to avoid lingering idle connections.<\/li>\n<\/ul>\n<p>Monitor the ratio of aborted connections and threads_created to see if your thread_cache_size and max_connections are appropriate.<\/p>\n<h3><span id=\"Disable_old_query_cache_and_use_proper_indexes\">Disable old query cache and use proper indexes<\/span><\/h3>\n<p>If you are running older MySQL versions that still have the classic <strong>query_cache<\/strong>, it is generally best to disable it for Moodle:<\/p>\n<ul>\n<li><strong>query_cache_type = 0<\/strong><\/li>\n<li><strong>query_cache_size = 0<\/strong><\/li>\n<\/ul>\n<p>Query cache can become a global contention point on write-heavy systems like Moodle. InnoDB buffer pool plus application-level caching (Redis\/Memcached) are far more effective.<\/p>\n<p>Indexes are mostly handled by Moodle core, but custom reports or third\u2011party plugins sometimes create slow, unindexed queries. Enable the slow query log and review it regularly, just as we recommend in MySQL-heavy setups for other apps.<\/p>\n<h3><span id=\"Storage_and_IO_considerations\">Storage and I\/O considerations<\/span><\/h3>\n<p>Moodle generates a lot of small writes (logs, sessions, tracking). Using fast SSD or NVMe storage dramatically reduces I\/O wait. If you are planning a new deployment, consider:<\/p>\n<ul>\n<li>Storing database data and logs on NVMe or high-performance SSD<\/li>\n<li>Separating database volume from Moodledata storage when possible<\/li>\n<li>Monitoring <strong>iowait<\/strong> and disk latency under load tests<\/li>\n<\/ul>\n<p>We go into more detail on measuring IOPS and disk latency in our <a href=\"https:\/\/www.dchost.com\/blog\/en\/yeni-vps-aldiginizda-ilk-yapmaniz-gerekenler-cpu-disk-ve-ag-performansini-benchmark-ile-test-etmek\/\">checklist for benchmarking CPU, disk and network performance on a new VPS<\/a>. The same approach helps validate whether your Moodle database volume can handle exam day.<\/p>\n<h2><span id=\"Caching_Strategy_for_Moodle_Sessions_Application_Cache_and_Reverse_Proxy\">Caching Strategy for Moodle: Sessions, Application Cache and Reverse Proxy<\/span><\/h2>\n<p>Moodle has its own caching subsystem (MUC) and supports multiple backends. Getting caching right can transform the user experience, especially during peak usage and for pages that repeat similar queries.<\/p>\n<h3><span id=\"Separate_session_storage_from_database\">Separate session storage from database<\/span><\/h3>\n<p>By default, some installations use the database for PHP sessions. This quickly becomes a bottleneck under load. A better pattern is:<\/p>\n<ul>\n<li>Use Redis or Memcached for PHP sessions<\/li>\n<li>Use Redis again for Moodle\u2019s application cache (MUC), but in a separate database \/ namespace<\/li>\n<\/ul>\n<p>Redis tends to be the first choice because it supports persistence options and advanced data types, but Memcached is also solid for pure caching. We compare these tradeoffs in detail for another PHP CMS in our article <a href=\"https:\/\/www.dchost.com\/blog\/en\/wordpress-ve-woocommerce-icin-redis-mi-memcached-mi-kalici-nesne-onbellegi-ttl-ve-eviction-ayarlarini-ne-zaman-nasil-yaparsin\/\">Redis vs Memcached for object caching, TTLs and eviction tuning<\/a>; the same logic applies very well to Moodle.<\/p>\n<h3><span id=\"Configuring_Redis_for_Moodle\">Configuring Redis for Moodle<\/span><\/h3>\n<p>At a high level, a Moodle + Redis setup typically looks like this:<\/p>\n<ul>\n<li>Install Redis server on the same host or a separate cache server<\/li>\n<li>Configure PHP session handler to use Redis (via php.ini or FPM pool settings)<\/li>\n<li>Configure Moodle\u2019s cache stores to use Redis for <strong>Application<\/strong> and <strong>Session<\/strong> caches<\/li>\n<\/ul>\n<p>Redis settings to review:<\/p>\n<ul>\n<li><strong>maxmemory<\/strong>: Set based on available RAM; avoid hitting the OS OOM killer<\/li>\n<li><strong>maxmemory-policy<\/strong>: Use <strong>allkeys-lru<\/strong> or <strong>volatile-lru<\/strong> for pure cache stores; be more conservative if you also store sessions<\/li>\n<li>Persistence: For pure caches, you can disable AOF\/RDB; for sessions, most admins keep at least RDB snapshots<\/li>\n<\/ul>\n<p>For large Moodle sites, high-availability Redis (with Sentinel or cluster) makes sense, similar to how we design high-availability cache setups for other CMS platforms.<\/p>\n<h3><span id=\"Moodles_internal_cache_definitions\">Moodle\u2019s internal cache definitions<\/span><\/h3>\n<p>Within Moodle\u2019s admin interface, you can map different cache definitions to different stores. Common patterns:<\/p>\n<ul>\n<li>Use file cache only for small, low-frequency definitions<\/li>\n<li>Use Redis\/Memcached for high-traffic definitions like language strings, config and core data<\/li>\n<li>Keep <strong>cacheloader<\/strong> and <strong>session<\/strong> caches on fast in-memory stores<\/li>\n<\/ul>\n<p>After setting up cache stores, use Moodle\u2019s built-in cache performance diagnostics to check hit rates. If a definition is still hitting the database too often, consider remapping it to a faster store.<\/p>\n<h3><span id=\"Reverse_proxy_and_microcaching\">Reverse proxy and microcaching<\/span><\/h3>\n<p>Moodle is more dynamic than a blog, but many pages can still benefit from very short full-page caching when the same content is accessed repeatedly (course pages, resource views for anonymous or guest users). Using Nginx or another reverse proxy in front of PHP can offload a large percentage of requests.<\/p>\n<p>A technique we often use for PHP apps is <strong>microcaching<\/strong>: caching full responses for 1\u20135 seconds for anonymous or low\u2011change pages. That may sound tiny, but at scale it can cut PHP load dramatically. We explain this pattern in more depth in <a href=\"https:\/\/www.dchost.com\/blog\/en\/nginx-mikro-onbellekleme-ile-php-uygulamalarini-ucurmak-1-5-sn-cache-bypass-ve-purge-ne-zaman-nasil\/\">our Nginx microcaching article<\/a>; for Moodle you must be more careful with logged\u2011in users, but there are still safe opportunities, especially for static assets and public content.<\/p>\n<h2><span id=\"Web_Server_and_PHPDB_Interaction_Details\">Web Server and PHP\u2013DB Interaction Details<\/span><\/h2>\n<p>Beyond the big blocks (PHP, DB, caching), a few web\u2011server and integration details make Moodle more predictable under load.<\/p>\n<h3><span id=\"Keep-Alive_and_connection_reuse\">Keep-Alive and connection reuse<\/span><\/h3>\n<p>Ensure HTTP keep\u2011alive is enabled so browsers can reuse connections for CSS, JS and images. This reduces CPU and improves perceived speed. Typical Nginx settings:<\/p>\n<ul>\n<li><strong>keepalive_timeout<\/strong>: 10\u201320s<\/li>\n<li><strong>keepalive_requests<\/strong>: 100\u2013500<\/li>\n<\/ul>\n<p>On Apache with event or worker MPM, also tune the number of workers and MaxRequestWorkers so that concurrent clients don\u2019t exhaust resources during peak sessions.<\/p>\n<h3><span id=\"Static_content_offload_and_compression\">Static content offload and compression<\/span><\/h3>\n<p>Moodle serves many CSS\/JS files and course resources. Offloading static content to a CDN or at least enabling aggressive browser caching reduces server load:<\/p>\n<ul>\n<li>Serve static assets with <strong>Cache-Control<\/strong> headers and long TTLs, using asset versioning<\/li>\n<li>Enable Brotli or gzip compression for text content (HTML, CSS, JS)<\/li>\n<li>Store large file areas on fast storage or object storage when appropriate<\/li>\n<\/ul>\n<p>For a broader look at how CDNs and caching affect traffic and cost, you can review our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/cdn-trafik-maliyetlerini-kontrol-altina-almak-origin-pull-cache-hit-ratio-ve-bolgesel-fiyatlandirma\/\">controlling CDN bandwidth costs via cache hit ratio and origin pull<\/a>; the same levers apply to LMS traffic.<\/p>\n<h3><span id=\"Cron_and_scheduled_tasks\">Cron and scheduled tasks<\/span><\/h3>\n<p>Moodle relies heavily on cron for background work: sending notifications, cleaning up temp data, running analytics and more. Poorly tuned cron can clash with real users:<\/p>\n<ul>\n<li>Run <strong>admin\/cli\/cron.php<\/strong> via system cron or a scheduler, not via web-initiated cron<\/li>\n<li>Run it every minute or at least every 5 minutes on active sites<\/li>\n<li>Monitor runtime; if cron regularly overlaps itself, consider splitting tasks across multiple workers or scaling resources<\/li>\n<\/ul>\n<p>Offloading cron to CLI also avoids web timeouts and makes resource usage more predictable.<\/p>\n<h2><span id=\"Monitoring_Capacity_Planning_and_Practical_Checklists\">Monitoring, Capacity Planning and Practical Checklists<\/span><\/h2>\n<p>All of these settings only work if you can see how your Moodle behaves in real life. A few lightweight monitoring practices go a long way.<\/p>\n<h3><span id=\"Key_metrics_to_watch\">Key metrics to watch<\/span><\/h3>\n<ul>\n<li><strong>CPU usage<\/strong> per core: Are PHP or DB saturating a single vCPU?<\/li>\n<li><strong>RAM usage<\/strong>: Are you swapping during exams?<\/li>\n<li><strong>Disk I\/O and iowait<\/strong>: Are database writes competing for disk time?<\/li>\n<li><strong>PHP-FPM status<\/strong>: Queue length, idle vs busy workers, slow logs<\/li>\n<li><strong>Database metrics<\/strong>: InnoDB buffer pool hit ratio, slow queries, lock waits<\/li>\n<li><strong>Redis\/Memcached stats<\/strong>: cache hit rate, eviction counts<\/li>\n<\/ul>\n<p>Even simple tools like <code>top<\/code>, <code>vmstat<\/code>, <code>mysqltuner<\/code> and Redis&#8217; <code>INFO<\/code> can show where the real bottleneck is before you start throwing more hardware at the problem.<\/p>\n<h3><span id=\"Practical_preexam_checklist\">Practical pre\u2011exam checklist<\/span><\/h3>\n<p>Many Moodle environments have a predictable peak: midterms, finals or company\u2011wide training days. In the weeks leading up to a peak event, run through a short checklist:<\/p>\n<ul>\n<li>Verify OPcache is enabled and not constantly restarting<\/li>\n<li>Confirm Redis\/Memcached is used for sessions and key Moodle caches<\/li>\n<li>Review <strong>innodb_buffer_pool_size<\/strong> and ensure the buffer pool hit ratio is high<\/li>\n<li>Load test the main workflows (login, quiz start, quiz submit, reports)<\/li>\n<li>Check PHP-FPM slow logs for any scripts consistently taking too long<\/li>\n<\/ul>\n<p>If you are unsure whether your existing plan has enough headroom, the signals we describe in <a href=\"https:\/\/www.dchost.com\/blog\/en\/hosting-paketinizi-yukseltmeniz-gerektigini-gosteren-9-sunucu-tarafli-sinyal\/\">our guide to server\u2011side signs it\u2019s time to upgrade your hosting plan<\/a> map very closely to Moodle behaviour: persistent high CPU, long TTFB and frequent resource limit errors.<\/p>\n<h2><span id=\"Bringing_It_All_Together_A_Calm_Path_to_a_Fast_Moodle\">Bringing It All Together: A Calm Path to a Fast Moodle<\/span><\/h2>\n<p>Optimising Moodle hosting performance is less about chasing exotic tweaks and more about getting the basics right and keeping them consistent. Modern PHP with a tuned FPM pool, a healthy OPcache and sensible PHP limits give each request a fair chance. A well\u2011sized InnoDB buffer pool, realistic connection limits and a watchful eye on slow queries keep the database from becoming the bottleneck every time a class starts a quiz. Redis or Memcached take pressure off both PHP and MySQL, while short\u2011TTL microcaching and static asset offload ensure your web server isn\u2019t re\u2011doing unnecessary work.<\/p>\n<p>At dchost.com we see these same patterns across many PHP applications, and Moodle fits neatly into them. If you are planning a new LMS, consolidating several Moodle instances, or simply want to stabilise an overloaded server before the next exam season, start with the settings in this guide and then measure. Small, targeted changes often bring surprisingly big gains once the underlying architecture is sound. And if you need a hosting environment\u2014whether shared, VPS, dedicated or colocation\u2014that can grow with your LMS and give you room for proper PHP, database and caching tuning, our team is ready to help you design and operate a stack that keeps your Moodle fast, predictable and calm under real\u2011world load.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>If you run Moodle or another PHP-based LMS, you quickly learn that raw CPU and RAM are only half the story. Two platforms with the same server specs can feel completely different: one is smooth during peak exams, the other struggles with logins, quiz attempts and reports. The missing piece is usually how PHP, the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2831,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-2830","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teknoloji"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/2830","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/comments?post=2830"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/2830\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media\/2831"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media?parent=2830"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/categories?post=2830"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/tags?post=2830"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}