Skip to main content
Version: 2026.1

Performance issues while manipulating images

Pimcore generates thumbnails on the fly when they are not created yet, see https://docs.pimcore.com/platform/Pimcore/Assets/Working_with_Thumbnails/Image_Thumbnails/#dynamic-generation-on-request.

Thumbnail creation, like all image processing tasks, is CPU & RAM intensive.

The creation of a thumbnail is controlled by PHP, which relies on ImageMagick.

Creating a single thumbnail can consume more resources than what's available in the quota granted to your PHP container.

Many factors can influence the amount of RAM required:

  • The size of the image: width × height
  • The number of channels needed to encode the image. Channels represent color components (e.g. RGB=3, RGBA=4, CMYK=4, CMYK+Alpha=5).
  • The number of layers: layers are multiple images stored in a file (common in PSD/AI). There is usually only one layer for a JPEG, but it can be more. PSD files may have a high number of layers, for instance, we saw a PSD file with 23 layers.

Here are a few examples of images with their file size on disk and the amount of RAM required to create a thumbnail:

FormatFile sizeRAM required
File 1WEBP155kB155MB
File 2JPG10MB473MB
File 3JPG74MB2.7GB
File 4JPG125MB4.9GB
File 5JPG804MB2.2GB
File 6PSD154MB1GB
File 7PSD1.6GB24GB

Note: Values are from real measurements; actual usage may vary depending on channels, layers, bit depth, and concurrent load.

Why “file size ≠ memory usage” File size depends on compression; memory size depends on pixel count, bit depth, channels, and layers.

Rule of thumb for RAM usage
To estimate peak memory consumption when creating thumbnails:

RAM ≈ decoded size × 3–5   (single-layer images)  
RAM ≈ decoded size × 10+ (layered PSD/AI files)

where

  • decoded size = width × height × channels × bytes_per_channel
  • bytes_per_channel = 1 for 8-bit, 2 for 16-bit, etc.

Example:
A 6000×4500 RGB JPEG (8-bit, 3 channels):

decoded size = 6000 × 4500 × 3 × 1 ≈ 81,000,000 bytes ≈ 77 MB
estimated peak RAM ≈ 77 MB × 5 ≈ 385 MB

In practice, ImageMagick used ~473 MB — close to this estimate.

How to check the memory usage

You can check the amount of RAM required to process the image by running the following command: grep VmHWM /proc/PID/status where PID is the PID of the PHP-FPM worker that processed the request.

You can also log ImageMagick resource activity by adding the following ENV variables in your Pimcore PaaS environment:

env:MAGICK_DEBUG: resource,cache
env:MAGICK_LOG_FORMAT: "%t %e %r %u %p %m %s"

You'll find all the debug outputs in /var/log/app.log. You can search for Heap Memory: grep "Heap Memory" /var/log/app.log. (Remember to remove these ENV variables once they are no longer needed.)

Unfortunately, you can't rely on the amount of RAM reported in /var/log/php.access.log. It only counts the RAM consumed by PHP itself. Any external command, such as ImageMagick, is not taken into account.

You may also wonder if this memory consumption will be seen in Metrics. The answer is: it depends on whether the process keeps memory long enough for Metrics to measure it.

PHP-FPM workers - Parallelism

Keep in mind that PHP-FPM workers are spawned up to the pm.max_children value. So a single person browsing the Pimcore admin and clicking on a folder can, by default, trigger the creation of 25 thumbnails in parallel. Depending on the number of workers and the complexity of the images, the system can quickly run out of resources. For instance, if each thumbnail can require 1 GB, and pm.max_children=10, the container may need up to ~10 GB RAM to survive concurrent generation. It can impact not only the rendering of images but also the standard PHP processing of typical requests, such as browsing the admin interface. It can result in the admin being completely stuck.

You can influence the number of PHP-FPM workers by adding the sizing_hints to your PHP app container, check https://fixed.docs.upsun.com/languages/php/fpm.html.

Remember a few things about PHP-FPM workers:

  • One PHP-FPM worker can only process one HTTP request at a time,
  • When all PHP-FPM workers are busy processing requests, the other incoming requests are placed into a queue until a worker has completed its task.

When the memory limit of your PHP container is reached, the system may kill PHP-FPM workers. You'll find a line related to this action in /var/log/app.log. Example:

[08-Sep-2025 09:04:27] WARNING: [pool web] child 334 exited on signal 9 (SIGKILL) after 113.799485 seconds from start

What should I do if I run into this issue?

Check the resource allocation

The first thing is to review the memory allocation for your app container. You may need to adjust the size or even use Flexible Resources: https://fixed.docs.upsun.com/create-apps/flexible-resources.html. You need to ensure the container has enough memory to run concurrent resizes (multiple PHP-FPM workers running simultaneously and resizing images).

If your plan doesn't include enough resources for creating thumbnails of your images, please contact your Pimcore Sales representative to upgrade to a larger plan.

Adjust the ImageMagick policy

You can also adapt your Pimcore PaaS configuration to fit your needs.

The first file you can tweak is .magick/policy.xml. You may adjust:

  • memory: amount of RAM that ImageMagick can use for a single request
  • map: amount of Linux swap that ImageMagick can use for a single request
  • disk: amount of disk storage in /tmp that ImageMagick can use for a single request
  • thread: amount of vCPU that ImageMagick can use for a single request

ImageMagick will always try to allocate as much RAM as it can. If that isn’t enough, it will use Linux swap, and finally write to /tmp if needed.

Note: /tmp is limited to 8GB on Pimcore PaaS

Keep in mind that these parameters are for a single instance of ImageMagick. With PHP-FPM workers, you may have multiple instances running in parallel. Numbers add up quickly.

Isolate image processing into a dedicated container

To avoid overloading the PHP-FPM workers with thumbnail rendering, you can segregate the thumbnail PHP job from the usual PHP traffic. For this, you can simply duplicate your PHP container, naming it pimcore-assets, for instance. You'll need to keep the exact same build hook so that the same build artifact is used. Do not copy the deploy hook into this new container. Otherwise, tasks like database migrations would run twice.

You can then define the sizing_hints differently between the usual PHP container and the one dedicated to the thumbnail generation. The idea is to have more PHP workers dedicated to handling regular traffic rather than generating thumbnails. For instance, if you need 1GB of RAM on average to create thumbnails, then you can set request_memory=1024. It'll automatically limit the number of PHP-FPM workers.

The last thing to do is to configure your .platform/routes.yaml to direct part of the traffic to your new container:

   "https://www.{all}/admin/asset/get-image-thumbnail":
type: upstream
upstream: "pimcore-assets:http"
"https://www.{all}/admin/asset/download-image-thumbnail":
type: upstream
upstream: "pimcore-assets:http"
"https://www.{all}/Sample%20Content/":
type: upstream
upstream: "pimcore-assets:http"

With this configuration, even if all PHP-FPM workers are busy creating thumbnails, the admin and other PHP scripts will continue to work correctly.

FAQ

Why does my 2 MB JPG need hundreds of MB of RAM?

File size on disk depends on compression. In memory, the image is fully decoded: width × height × channels × bit depth. For example, a 6000×4500 RGB JPG (~10 MB) becomes ~77 MB decoded, and ImageMagick may use several working copies, resulting in ~400–500 MB RAM consumption.

Why do PSD or AI files consume so much memory?

These formats often contain many layers and sometimes extra channels (masks, spot colors). Each layer is decoded into its own pixel cache. We’ve observed PSDs with 20+ layers consuming 20–25 GB of RAM even though the file size was only 1.6 GB.

Can I rely on file size to know the memory usage?

No. A small compressed file (e.g. a 150 kB WebP) can expand to >150 MB in RAM, while a 20 MB JPG may only need ~500 MB. Always consider pixel dimensions, channels, and layers.

What does VmHWM mean and why is it useful?

VmHWM stands for High Water Mark. It’s the peak resident set size — the maximum physical RAM that a process has consumed since it started. Checking VmHWM in /proc/<pid>/status gives the most reliable number for real RAM usage.

Why is my Pimcore admin freezing when browsing assets?

When browsing a folder, Pimcore may generate many thumbnails in parallel. If each thumbnail uses hundreds of MB or even GBs, the PHP-FPM workers can quickly exhaust the container’s memory, blocking all requests until workers are killed or free up memory.

How can I prevent thumbnails from exhausting my container?

  • Adjust container sizing (sizing_hints, Flexible Resources).
  • Set ImageMagick policies (memory, map, disk, thread) to control resource usage.
  • Isolate thumbnail generation in a dedicated container with its own limits.
  • Pre-generate heavy thumbnails using the CLI or use an Upsun (Platform.sh) worker job instead of on-demand.