Technology

PHP Limits: Memory, Execution Time and File Uploads

PHP settings like memory_limit, max_execution_time and upload_max_filesize look like small configuration lines, but they can affect whether requests complete successfully or encounter memory errors, timeouts and failed uploads. They affect everything from WordPress and WooCommerce to Laravel, custom APIs, LMS platforms and even small corporate sites. The goal is not to push all limits to extreme values, but to set realistic numbers that match your code, traffic, and hosting resources.

In this guide, we will walk through what each of these PHP directives actually does in real life, common configuration mistakes, and suggested starting values for different types of projects. You will see how to change them on shared hosting, cPanel/DirectAdmin, and VPS or dedicated servers, and how to debug when you still hit limits. By the end, you will have a practical checklist you can apply to your hosting environment, subject to its available controls.

Why These PHP Settings Matter More Than You Think

From a distance, memory and time limits look like pure backend concerns. In practice, they shape user experience, SEO and even conversion rates. Here is what they really control:

  • memory_limit: Memory accounted to the script by PHP’s memory manager, not total worker RAM.
  • max_execution_time: A PHP execution timer whose accounting depends on platform and build; it is not always a wall-clock request deadline.
  • upload_max_filesize: A per-file upload limit. post_max_size separately limits the whole POST body, including files, fields and multipart overhead.

These directives interact with your web server (Apache, Nginx, LiteSpeed), database timeouts, and even CDN or WAF settings. They are also one of the root causes behind issues like the WordPress white screen problem. If you have struggled with that, you may want to read our detailed guide on fixing the WordPress White Screen of Death from the hosting side after finishing this article.

Understanding memory_limit: How Much PHP Memory Do You Really Need?

What memory_limit Actually Controls

memory_limit bounds script allocations accounted by PHP’s memory manager. In ordinary FPM web execution this applies to the current request; the worker can serve later requests too. It is not a cap on the process RSS, all native extension allocations, shared OPcache memory or database-server RAM. A large database result copied into PHP arrays can consume script memory, while the database engine’s own query memory is separate. PHP reports an error such as:

PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes)

134217728 bytes is 128 MiB (PHP’s 128M notation). Starting with PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12, memory_limit is a soft limit: some allocations may complete before the fatal error is raised. memory_hard_limit_percent adds a bound for this tracked memory; it still is not an operating-system cap on total process RAM. memory_get_peak_usage(true) measures the peak reserved by PHP’s memory manager, not the complete process footprint. Profile both script allocations and actual worker memory.

Example memory_limit Values and Where They May Fall Short

Illustrative memory_limit values to assess against your workload and RAM budget:

  • 64M or 128M for lighter workloads
  • 256M as a possible starting point for more demanding requests
  • 512M or more for heavy operations, where the RAM budget and concurrency limits permit

Workloads that may exceed these values include:

  • WordPress with many plugins: Page builders, security suites, analytics, WooCommerce, and translation plugins can push a request beyond 128M, depending on the workload.
  • WooCommerce, Magento or other e‑commerce: Bulk imports, large product catalogs, and complex cart/checkout logic can easily hit 256M or more.
  • LMS platforms (Moodle, custom LMS): Reporting, grade exports and complex queries often need more RAM during peak processes.
  • Image-heavy or PDF‑heavy workflows: Any script that resizes or manipulates large images or PDFs can spike memory usage.

We cover broader performance tuning for LMS workloads in our Moodle and LMS hosting performance guide, where memory_limit is one of the key levers.

How to Estimate a Reasonable memory_limit

There is no single magic number, but you can estimate a starting value by thinking about three things:

  1. The heaviest operation on your site (e.g. product import, backup, report)
  2. Concurrent PHP processes (how many requests can run at the same time)
  3. Total RAM available for PHP (after the OS, database, cache, web server, etc.)

Assume:

  • Suppose a heavy request completes within a 256M script limit.
  • The existing FPM pool allows 20 concurrent workers.
  • The VPS has 4 GiB RAM, with only 2 GiB reserved for PHP after other services.

20 × 256 MiB = 5120 MiB (5 GiB) is the sum of configured script limits, not allocated memory or a theoretical upper bound on process RAM. It already exceeds the 2 GiB PHP budget. For an illustrative sizing calculation, reserve 512 MiB of that budget for shared PHP memory and headroom, and assume a measured peak private footprint of 320 MiB per busy worker: floor((2048−512)/320)=4 workers. These are hypothetical measurements. Use representative peaks and validate CPU, queues and latency; do not treat average memory as a safe peak. Summing RSS double-counts shared pages; use private footprints plus a shared budget, or a group PSS measure without subtracting the same shared memory twice.

Practical Baselines for memory_limit

The following are suggested starting points, not measured requirements; validate them against your application’s peak memory use and concurrency:

  • Simple blogs or small business sites: 128M–256M
  • Standard WordPress with several plugins: 256M
  • WooCommerce or other e‑commerce: 256M–512M (sometimes higher for large stores)
  • LMS, CRM, ERP, SaaS backends: 512M+ for heavy admin operations, with appropriate worker limits

These must align with available RAM. On a tiny shared hosting plan, jumping to 1024M memory_limit does not magically give you more RAM; it just makes it easier to overload the server. On a VPS or dedicated server where you have administrative access and use PHP-FPM, tune the pool limits and memory_limit together against the available RAM.

For a more holistic look at server-side tuning for WordPress, including PHP-FPM and OPcache, you may also want to read our article The Server-Side Secrets That Make WordPress Fly.

How to Set memory_limit (php.ini, .htaccess and Per-Site)

You can change memory_limit via several methods, depending on hosting:

  • php.ini: the file loaded by the relevant PHP version and SAPI; CLI and FPM may differ.
  • .user.ini: per-directory configuration when enabled for CGI/FastCGI; only permitted INI_ALL, INI_USER and INI_PERDIR settings apply.
  • .htaccess php_value: Apache mod_php with the necessary AllowOverride permission. This is not a generic FPM method and may cause HTTP 500 with an unsupported handler.
  • Panel UI: the tool exposed for the selected domain/version. cPanel MultiPHP INI Editor edits INI settings; PHP Selector is a separate component when installed.

Examples:

; php.ini or .user.ini
memory_limit = 256M
# Apache mod_php only; required AllowOverride permission must be enabled.
php_value memory_limit 256M
<?php
// Current execution only; a false return means the change failed.
$previous = ini_set('memory_limit', '256M');
if ($previous === false) {
    throw new RuntimeException('memory_limit could not be changed');
}

An FPM php_admin_value cannot be overridden with ini_set. PHP 8.5 also offers startup-only max_memory_limit as a ceiling on memory_limit. Inspect the effective value in the target web request after editing; saving a file does not prove it was loaded. Managing multiple PHP versions per site explains version selection. A CGI/FastCGI .user.ini is cached for user_ini.cache_ttl, 300 seconds by default; a restart is not inherently needed for every such edit.

Understanding max_execution_time: Limiting Script Execution Time

What max_execution_time Controls

max_execution_time is a PHP execution timer in seconds. Default Unix/Linux CPU-time tracking normally excludes time spent in system calls, waiting on streams and external database work. Windows measures elapsed time. There is also a Unix build distinction: PHP compiled with --enable-zend-max-execution-timers uses POSIX per-thread elapsed timers, so sleeping and I/O waits count; that option is the default for ZTS builds since PHP 8.3. Verify the build and SAPI. A value of 30 does not universally mean termination at the 31st wall-clock second.

Distinguish documented defaults from example overrides:

  • PHP’s documented max_execution_time default is 30 seconds.
  • The CLI default is 0, meaning no PHP execution-time limit; loaded configuration or command-line options can change it.
  • 60–120 seconds for a selected administrative task, or 300–600 for a controlled batch job, are illustrative overrides rather than PHP defaults.

CLI does not ignore a positive max_execution_time. Long-running workers may deliberately keep 0, but need explicit job, process and external-service limits plus supervision. Cron schedules a start; it does not by itself enforce a runtime deadline or restart a failed worker. Queue and process-manager limits must be configured and tested, not assumed from their presence.

Diagnosing Operations That Time Out

Operations that can encounter one of the stack’s timeout limits include:

  • Large imports/exports (CSV, XML, product lists, user lists)
  • Backup or migration plugins that try to run everything in one go
  • Heavy admin pages (large reports, analytics, or complex filters)
  • API calls to slow third-party services where your script is waiting for an external response

A repeatable stop near 30 seconds is a diagnostic clue, not proof of PHP’s timer. Check the PHP error and the FPM/web/proxy logs, especially if the operation spends time waiting on a database or external HTTP service.

Example Ranges for max_execution_time

We like to think in tiers:

  • Regular web requests: 30–60 seconds is an illustrative ceiling, not a response-time target. Profile slow requests and move long operations out of the interactive path.
  • Authenticated administrative work: consider a 60–120-second override only for a justified operation, with matching resource and upstream limits.
  • Background/CLI tasks: choose the PHP timer deliberately. If 0 is needed for a persistent worker, configure independent job deadlines, overlap/retry handling and process supervision.

Raising max_execution_time does not make slow code fast. It extends that PHP timer, while other deadlines remain independent. Profile slow queries, external calls and processing work before choosing a larger value.

Timeouts Exist Across the Stack

One common troubleshooting trap: even if you increase PHP’s max_execution_time, you might still hit timeouts elsewhere:

  • Web server: Apache, Nginx, or LiteSpeed have their own request and proxy timeouts.
  • Load balancer / reverse proxy: Upstream timeouts may be shorter than PHP’s.
  • Database: MySQL/MariaDB and PostgreSQL have query and connection timeouts.
  • CDN or WAF: Request and response limits depend on the provider, plan and protocol; consult the active configuration.

That is why serious performance work always involves checking logs across components. If you want to get comfortable reading web server logs for 4xx and 5xx issues, have a look at our guide on diagnosing 4xx–5xx errors on Apache and Nginx.

How to Set max_execution_time

Common ways to set it:

; php.ini or .user.ini
max_execution_time = 60
# Apache mod_php only; required AllowOverride permission must be enabled.
php_value max_execution_time 60
<?php
// Current execution only; this restarts the execution-time counter.
if (ini_set('max_execution_time', '60') === false) {
    throw new RuntimeException('max_execution_time could not be changed');
}

A successful change resets the PHP execution-time counter; repeated resets are not a fixed overall deadline. FPM request_terminate_timeout and HTTP/database client timeouts are independent. A proxy timeout does not prove the upstream PHP work stopped.

Before you increase it too far, ask yourself: can this operation be restructured? For example, a WooCommerce product import can often be split into smaller batches via the plugin configuration, instead of trying to process 100,000 products in one monstrous request.

upload_max_filesize and post_max_size: Getting File Uploads Right

How upload_max_filesize and post_max_size Work Together

PHP uses two directives to control uploads and POST data:

  • upload_max_filesize: The maximum size of a single uploaded file.
  • post_max_size: The maximum size of the entire POST request body (including all files and form fields).

Some key rules:

  • post_max_size must be larger than upload_max_filesize to leave room for multipart boundaries, headers and other fields.
  • For multiple files, budget the sum of all file sizes plus that overhead. M means 1024×1024 bytes in these PHP settings.
  • Check max_file_uploads, file_uploads, temporary directory capacity/permissions, input parsing time and application policy as well as upstream body limits.

This equal-size configuration is a diagnostic counterexample, not the recommended setup:

upload_max_filesize = 32M
post_max_size = 32M

A full 32 MiB file cannot fit into a 32M POST budget because the multipart request adds overhead. The following larger POST budget allows a 32 MiB file with room for normal form data; it still cannot hold two full 32 MiB files plus overhead:

upload_max_filesize = 32M
post_max_size = 64M

Typical Values for Different Sites

Choose an allowed per-file size from actual product requirements. These are illustrative limits to test, not guarantees that each file can be decoded or processed within memory_limit:

  • Standard content sites: 8M–16M (for images and small PDFs)
  • Corporate / portfolio / blogs: 16M–32M (enough for larger images, short videos, PDFs)
  • E‑commerce with product images: 32M–64M (raw images, optimized later)
  • LMS and file sharing features: 64M–256M or more, depending on your policy

Always tie this to a clear policy: what is the maximum file size you are comfortable with, given storage, bandwidth and security constraints? Setting everything to 1 GB just “in case” usually creates more problems than it solves, especially on smaller VPSs or shared hosting plans.

Do Not Forget Web Server Limits

Even if PHP allows 64M uploads, the web server might block them first. Examples:

  • Nginx: client_max_body_size.
  • Apache: LimitRequestBody or module-specific limits.
  • Reverse proxies/CDNs: their own request-body and duration limits, checked before PHP may receive the request.

For a single 64 MiB file, this example allows an 80 MiB request body at both Nginx and PHP, leaving 16 MiB for fields and multipart overhead. It is not a two-file 64 MiB allowance. Adapt the request budget to the actual form:

# Nginx http/server/location context for the intended upload route.
client_max_body_size 80M;
; Relevant PHP SAPI configuration
upload_max_filesize = 64M
post_max_size = 80M

How to Set upload_max_filesize and post_max_size

Use the applicable configuration mechanism described above. upload_max_filesize and post_max_size are INI_PERDIR directives; ini_set in the upload-handling script cannot raise them after the body has already been parsed:

; php.ini or .user.ini
upload_max_filesize = 32M
post_max_size = 64M
# Apache mod_php only; required AllowOverride permission must be enabled.
php_value upload_max_filesize 32M
php_value post_max_size 64M

A per-file limit violation can appear as UPLOAD_ERR_INI_SIZE (1) in the file error entry. With ordinary PHP POST parsing, exceeding post_max_size leaves both $_POST and $_FILES empty. An upstream body limit can return 413 before PHP executes. Handle each condition explicitly; silent failure is not inevitable. Uploads may stream to temporary files rather than reside wholly in PHP memory, but decoding images/PDFs can require much more memory than their compressed size. Enforce authentication, quotas, content/type validation and non-executable storage; a small allowed file is not automatically safe.

Changing PHP Settings on Shared Hosting, VPS and Dedicated Servers

On Shared or cPanel/DirectAdmin Hosting

On shared hosting, available controls and upper bounds depend on the plan and PHP handler. Inspect the settings actually exposed for the target domain:

  • Use the panel’s INI editor or PHP settings tool. cPanel MultiPHP Manager selects versions/handlers; MultiPHP INI Editor edits permitted INI values. A separately installed PHP Selector has its own options.
  • Use .user.ini only when CGI/FastCGI scanning is enabled, or .htaccess php_value only with the supported Apache module configuration.

Example workflow on cPanel-like environments:

  1. Select the correct domain and PHP version.
  2. Record the current effective values and application requirements before choosing a test profile.
  3. Adjust a justified limit and save. Observe the relevant reload or .user.ini cache interval.
  4. In staging, test normal operations plus single-file and total-request boundary failures. Check web/PHP logs and account CPU/RAM/I/O limits.
  5. Verify the effective values through a protected web request and remove the temporary diagnostic afterward.

If you are frequently hitting resource ceilings on shared hosting even after tuning PHP settings, it is worth reading our article on how to avoid the “Resource Limit Reached” error on shared hosting. It explains CPU, memory and I/O limits at the account level, which exist above PHP’s own limits.

On VPS and Dedicated Servers

With the necessary administrative access on a VPS or dedicated server, you can manage the relevant components. Paths below follow a Debian-style layout and are examples, not universal locations:

  • Global PHP configuration (/etc/php/<version>/fpm/php.ini, cli/php.ini, etc.)
  • Per-pool PHP-FPM configs to tune worker counts and memory usage
  • Web server settings (Nginx/Apache body size and timeout directives)

The following example returns to the earlier 2 GiB PHP budget and four-worker sizing illustration. The php.ini section belongs to the actual FPM version; the pool fragment must be merged into an existing valid pool with its user, group and listener already configured:

; Example: /etc/php/8.2/fpm/php.ini; use your installed FPM version.
; Example per-site PHP configuration; validate workload and concurrency.
memory_limit = 256M
max_execution_time = 60
upload_max_filesize = 32M
post_max_size = 64M
; Merge into an existing valid PHP-FPM pool; not a complete pool file.
; Illustrative 2 GiB PHP budget, measured private peak 320 MiB/worker.
pm = dynamic
pm.max_children = 4
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_requests = 500

pm.max_children=4 limits this pool to four simultaneous requests; additional demand can queue. The illustrative 320 MiB private peak per worker and 512 MiB shared/headroom reservation fit the 2 GiB budget, but actual peaks and CPU/latency still need measurement. memory_limit=256M is neither preallocated nor a complete process cap. pm.max_requests=500 recycles a child after that many requests; it does not repair a leaking request or cap its execution time. Validate the pool configuration and use the installed service’s reload procedure. Changing Nginx requires its own syntax check/reload; a .user.ini edit follows its cache interval.

If you regularly handle larger loads or mission-critical applications, we strongly recommend pairing PHP tuning with broader performance and capacity planning. Our article on how much CPU, RAM and bandwidth a new website needs is a good starting point before you choose your VPS or dedicated specs at dchost.com.

Recommended Baselines and a Practical Tuning Checklist

Baseline Settings for Common Use Cases

These test profiles describe workloads, not hosting plan guarantees. Validate application-version requirements, measured peaks, concurrency and the total RAM budget. The LMS POST example assumes one 256 MiB file; multiple files require a separately calculated total:

Use casememory_limitmax_execution_timeupload_max_filesizepost_max_size
Small blog/corporate site128M–256M30–60s16M–32M64M
Standard WordPress256M60s32M64M
WooCommerce256M–512M60–120s for selected admin work64M128M
LMS/CRM/heavy admin work512M+ only if measured need fits capacity120–300s only for controlled tasks; consider CLI/queues64M–256M272M for one 256M file plus limited form data

Always validate against real usage: check logs, run imports or backups on staging, and watch resource graphs.

A Step-by-Step Tuning Checklist

  1. Identify heavy operations and record the effective PHP version, SAPI and values.
  2. Find the specific error in PHP/web logs; a 500 or timeout alone does not identify the limiting directive.
  3. Measure script-accounted peaks and actual worker/group memory, then reserve resources for other services and concurrency.
  4. Optimize/batch the expensive operation and change a justified limit in small steps, testing after each change.
  5. Budget uploads by per-file size and whole POST size including overhead; align upstream limits and test rejection paths.
  6. Give background work explicit deadlines, retry/overlap controls and external-service timeouts.
  7. Watch memory, CPU, I/O, queues and latency under representative load; keep the old configuration available for rollback.

For a temporary check, serve this only through an access-restricted test path in the actual web SAPI. Remove it afterward; do not leave a public phpinfo() page. CLI output does not establish the FPM values:

<?php
// Temporary protected diagnostic; remove after verification.
header('Content-Type: application/json');
echo json_encode([
    'sapi' => PHP_SAPI,
    'memory_limit' => ini_get('memory_limit'),
    'max_execution_time' => ini_get('max_execution_time'),
    'upload_max_filesize' => ini_get('upload_max_filesize'),
    'post_max_size' => ini_get('post_max_size'),
], JSON_PRETTY_PRINT);

If you are in the process of upgrading to PHP 8.x, make sure you also review our PHP 8.x upgrade checklist, where we combine version upgrades, OPcache tuning and PHP-FPM pool settings with these basic directives.

Troubleshooting When You Still Hit Limits

If you have increased limits and still face issues:

  • Look for specific error messages in PHP and web server logs, not just on screen.
  • Check cPanel or panel resource usage charts to see if CPU/IO/EP limits are being hit.
  • Profile slow pages or operations: sometimes one plugin or query is the entire problem.
  • Use staging to reproduce and test with different settings before changing production.

Our article on understanding cPanel resource limits is a useful companion here, because it explains the outer boundaries that surround your PHP settings on shared hosting.

When PHP Settings Are Not Enough: Time to Rethink Hosting

Sometimes the problem is not your config values, but the physical limits of your hosting environment. Signs that it is time to upgrade or re-architect include:

  • You have already set reasonable PHP limits and optimized code, but still hit memory or CPU bottlenecks.
  • Simple traffic spikes regularly push your site into 500 errors or timeouts.
  • You need consistently higher upload limits and background processing than shared hosting comfortably supports.
  • Your site is growing into a full e‑commerce or SaaS platform with predictable high loads.

In those cases, moving from entry-level shared hosting to a VPS or dedicated server is often the cleanest next step. At dchost.com, we provide shared hosting, VPS, dedicated and colocation options, so you can match PHP limits with actual hardware resources instead of fighting within tight ceilings.

For a structured way to detect when an upgrade is truly necessary, not just “nice to have”, you can check our article on server-side signals that it is time to upgrade your hosting plan. Combining those signals with the PHP tuning steps in this article will give you a clear roadmap.

Wrapping Up: Make PHP Limits Work For You, Not Against You

PHP settings like memory_limit, max_execution_time and upload_max_filesize are not just random numbers you copy from a tutorial. They are guardrails that protect your server resources while still allowing your applications to do real work. When they are too low, you see white screens, broken uploads and failed imports. When they are too high on undersized infrastructure, a few heavy requests can consume all RAM or CPU and slow down everything else.

The best approach is systematic: understand what each directive does, start from sane baselines for your type of site, and then adjust based on actual usage, logs and monitoring. On shared hosting, use panel tools and per-directory configuration to stay within account limits. On VPS or dedicated servers, combine PHP settings with tuned PHP-FPM pools, web server limits and properly sized hardware.

If you need help evaluating a DCHost configuration, provide the PHP version/SAPI, relevant error and workload/resource measurements without passwords or access tokens. Review the values again after application, plugin, traffic or upload-policy changes; a one-time setting cannot guarantee future capacity.

Frequently Asked Questions

One test profile is 256M memory_limit, 60 seconds max_execution_time, 32M upload_max_filesize and 64M post_max_size. Check the installed application requirements and test real operations; these values are not guaranteed minima or a performance target. Match FPM concurrency to measured worker memory and the total budget. Raising a limit does not allocate RAM or speed up code.

The cause may be another timeout, a code/plugin failure or account CPU/RAM/I/O limits. Check the exact PHP and web-server error before changing settings. Reproduce on staging and profile the operation. PHP-accounted memory differs from total worker RAM and database-server memory; a higher script limit cannot overcome an exhausted account or server budget.

The first limits each file; the second covers the entire POST body, including all files, form fields and multipart overhead. Set post_max_size above the file limit and budget multiple files explicitly. Two full 32 MiB files exceed a 64M POST budget. Align upstream body limits, check temporary storage and validate file content, authorization and processing-memory needs.

Often. CLI defaults max_execution_time to 0 but still enforces a configured positive value according to the platform/build timer. A persistent worker may use 0 with explicit job/process deadlines, retry and overlap controls, external-service timeouts and supervision. Cron only schedules execution. Keep CLI memory and concurrency within the same host budget as web workers and other services.

After profiling and optimization, compare representative peaks and concurrency with the available RAM, CPU and I/O budget. Persistent queues, saturation or account-limit failures may require a different workload design or more capacity. A higher PHP limit does not supply extra resources. Select capacity from measurements and recovery/operational requirements rather than site category alone.
↑