PrestaShop 9 Performance Optimization: Complete Guide

69 Views

A slow PrestaShop store rarely has one single cause.

Performance is the combined result of PHP, database queries, modules, hooks, images, storage, cache configuration, background jobs, web-server settings, third-party services and the way the catalog grows over time.

PrestaShop 9 provides a stronger technical foundation than earlier generations. It uses Symfony 6.4, supports modern PHP versions, includes native WebP and AVIF image support, and contains several front-office and rendering improvements.

But upgrading to PrestaShop 9 does not automatically make every store fast.

A poorly written module can still execute an expensive SQL query on every page. A supplier import can still saturate CPU and disk. A theme can still load oversized product images. A large database can still suffer from missing indexes.

The right way to optimize PrestaShop 9 is therefore:

measure → identify the bottleneck → make one change → measure again

That principle is also reflected in PrestaShop's own performance documentation.

This guide provides a practical optimization process for real production stores.

Version note: This article was verified on September 22, 2026. PrestaShop 9.1 currently recommends PHP 8.5, while PrestaShop 9.0 recommends PHP 8.4. Always test your modules and theme against the exact PHP version you plan to use.

1. Establish a Performance Baseline

Do not start by changing random settings in the Back Office.

First, measure the store.

At minimum, record performance for:

  • homepage;
  • category page;
  • product page;
  • search;
  • cart;
  • checkout;
  • Back Office product page;
  • Back Office order page.

Measure more than total browser load time.

Useful metrics include:

  • Time to First Byte (TTFB);
  • PHP execution time;
  • database query time;
  • number of SQL queries;
  • total transferred bytes;
  • Largest Contentful Paint;
  • Interaction to Next Paint;
  • Cumulative Layout Shift;
  • PHP memory usage;
  • slowest cron duration.

This creates a reference point.

If you change PHP-FPM settings and TTFB becomes 15% worse, you know the change did not help.

Without a baseline, optimization becomes guesswork.

2. Test Production-Like Conditions

Do not benchmark only with debug mode enabled.

Developer mode changes application behavior and may disable or alter caching.

Likewise, do not measure only while logged in as an administrator if most customers browse anonymously.

Test:

  • anonymous visitor;
  • customer with a cart;
  • logged-in customer;
  • mobile device;
  • desktop device.

Also repeat tests with background jobs active.

A store may feel fast at 03:00 when nothing else is running but become slow every morning when a supplier import starts.

3. Find the Real Bottleneck

A slow page can be caused by different layers.

CPU bottleneck

Symptoms may include:

  • PHP workers at high CPU;
  • image processing slowing the server;
  • imports competing with customer traffic;
  • AVIF generation consuming significant CPU.

Memory bottleneck

Symptoms may include:

  • OOM kills;
  • PHP memory errors;
  • server swapping;
  • database cache being forced out of RAM.

Database bottleneck

Symptoms may include:

  • slow category pages;
  • Back Office grids timing out;
  • high database CPU;
  • slow-query log growth;
  • full table scans.

Disk bottleneck

Symptoms may include:

  • image generation becoming extremely slow;
  • high I/O wait;
  • database queries slow despite moderate CPU;
  • filesystem operations delaying cache generation.

Network bottleneck

Symptoms may include:

  • remote API calls delaying PHP;
  • slow third-party feeds;
  • CDN misconfiguration;
  • large images.

Do not optimize the wrong layer.

4. Use the Correct PHP Version

The current official PrestaShop 9 requirements recommend:

  • PHP 8.4 for PrestaShop 9.0
  • PHP 8.5 for PrestaShop 9.1

Running a modern supported PHP version can improve both performance and maintainability.

But do not switch production first.

Test:

  • core;
  • theme;
  • payment modules;
  • shipping modules;
  • imports;
  • cron;
  • CLI;
  • custom modules.

PHP errors often appear only in edge cases.

5. Enable OPcache

OPcache is one of the basic requirements of a performant PHP environment.

Without OPcache, PHP repeatedly parses and compiles application files.

PrestaShop has a large codebase, and modules add even more PHP files.

A production PHP configuration should normally have OPcache enabled.

Example settings may look like:

opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=50000
opcache.validate_timestamps=1

These values are examples, not universal recommendations.

Check actual OPcache statistics.

Important metrics include:

  • memory used;
  • free memory;
  • hit rate;
  • number of cached scripts;
  • restart count.

If OPcache constantly restarts because the cache is full, increase it based on evidence.

6. Do Not Disable Timestamp Validation Blindly

Some performance guides recommend:

opcache.validate_timestamps=0

This can reduce file checks.

However, it also means changed PHP files may not be detected until OPcache or PHP-FPM is restarted.

If your deployment process explicitly resets OPcache, this can be safe.

If administrators upload module files manually, it can produce confusing behavior where new code exists on disk but old bytecode still runs.

Performance configuration must match your deployment workflow.

7. Size PHP-FPM Correctly

Too few workers create queues.

Too many workers can exhaust RAM.

Suppose a real PrestaShop PHP worker consumes approximately 150 MB under load.

If you allow:

pm.max_children = 40

then the theoretical worker memory exposure is:

40 × 150 MB = 6000 MB

That does not include:

  • MySQL/MariaDB;
  • Redis;
  • Nginx/Apache;
  • operating system;
  • filesystem cache;
  • cron jobs.

On an 8 GB server, that configuration could be dangerous.

Measure average and peak worker memory and leave headroom.

8. Separate Web PHP from Heavy CLI Jobs

A customer loading a product page should not compete directly with a three-hour import using the same process model.

Heavy tasks should run through:

  • CLI;
  • cron;
  • queues;
  • dedicated workers.

Examples include:

  • supplier XML parsing;
  • image regeneration;
  • stock synchronization;
  • price updates;
  • sitemap generation;
  • feed generation.

This makes resource usage easier to control.

9. Profile Database Queries

Database optimization can produce some of the largest gains on large stores.

Enable the database slow-query log for a controlled period.

Look for:

  • queries scanning huge tables;
  • missing indexes;
  • repeated queries;
  • queries sorting large datasets;
  • joins exploding in cardinality.

Then use:

EXPLAIN

to inspect the execution plan.

Do not optimize based on query appearance alone.

A complex query can be fast with the right index.

A simple query can be disastrous if it scans millions of rows.

10. Add Indexes Based on Real Queries

Indexes are extremely useful, but they are not free.

Every index:

  • consumes storage;
  • uses memory;
  • increases write cost;
  • must be maintained during inserts and updates.

Suppose a module worker repeatedly runs:

SELECT *
FROM ps_module_queue
WHERE id_shop = 2
  AND status = 'pending'
ORDER BY id_queue
LIMIT 100;

A suitable composite index may dramatically reduce work.

For example:

(id_shop, status, id_queue)

But the correct index depends on the real query and data distribution.

Use EXPLAIN before and after.

11. Avoid SELECT * in Hot Paths

For occasional administrative queries, selecting every column may not matter.

For frequently executed queries over wide tables, it can waste:

  • database I/O;
  • network transfer;
  • PHP memory;
  • hydration time.

Select only the fields the operation actually needs.

This matters especially in:

  • queue workers;
  • product synchronization;
  • status endpoints;
  • dashboards.

12. Audit Large Tables

Inspect table sizes.

Common sources of uncontrolled growth include:

  • module logs;
  • import history;
  • queue history;
  • abandoned data;
  • visitor statistics;
  • temporary tables;
  • audit records.

Do not delete data merely because the table is large.

First determine:

  • who owns the data;
  • whether it is required for accounting;
  • whether it is required for support;
  • whether it is required for audit;
  • whether the module expects it.

Then create an explicit retention policy.

Inspect PrestaShop statistics storage before cleanup

Use the free Stats Table Guard Lite statistics scanner to review table-size estimates, connection history and statistics-collection status. It keeps this assessment read-only and may report partial metadata on restricted hosting.

If you need a separate preview-and-cleanup workflow, review Stats Table Guard Pro. Purchasing Pro is not enabled yet. Its described cleanup controls apply a retention period and explicitly started transactional batches to historical connection statistics; deleting rows does not guarantee an immediate reduction in database file size.

See the Stats Table Guard documentation for the scanning steps and edition scope.

13. Use Batching for Bulk Updates

A job that updates 100,000 products in a single transaction is difficult to operate.

Problems include:

  • long locks;
  • large transactions;
  • memory growth;
  • timeout risk;
  • difficult retries.

A safer design processes bounded batches:

100 products
→ save progress
→ next 100
→ save progress
→ continue

The optimal batch size depends on workload.

Test 50, 100, 500 or 1000 and measure.

14. Update Only Changed Products

One of the best optimizations for supplier synchronization is avoiding unnecessary writes.

If supplier data has not changed, do not rewrite the product.

A useful approach is a source hash.

For example:

normalized product data
        ↓
SHA-256 hash
        ↓
compare with stored hash
        ↓
unchanged → skip
changed → update

Large systems may maintain separate hashes for:

  • core product data;
  • price;
  • stock;
  • features;
  • images;
  • categories.

That way, an image change does not force every product field to be rewritten.

15. Profile Modules by Execution Cost

Do not assume a store is slow because it has “too many modules.”

The number of modules is not the key metric.

One inefficient module can be slower than fifty efficient modules.

Look for modules that:

  • run on global hooks;
  • execute many SQL queries;
  • call remote APIs during page rendering;
  • process large datasets on every request;
  • load unnecessary services;
  • calculate the same result repeatedly.

Disable non-essential modules one by one in staging and compare performance.

16. Avoid Remote HTTP Calls During Page Rendering

A product page should not wait on a third-party API unless absolutely necessary.

If a module executes:

customer request
→ PrestaShop
→ remote API
→ wait
→ render page

then the remote service becomes part of your page response time.

Better patterns include:

  • local cache;
  • background synchronization;
  • scheduled refresh;
  • asynchronous processing.

For example, exchange rates can be refreshed periodically instead of downloaded during every page load.

17. Audit Hook Execution

Some hooks run on many pages.

If a module attaches expensive logic to a global hook, the cost is multiplied by every request.

Profile:

  • header hooks;
  • footer hooks;
  • product display hooks;
  • cart hooks;
  • customer hooks.

Ask whether the operation must run every time.

A hook may only need to render previously cached data.

18. Use Native WebP and AVIF Support

PrestaShop 9 introduced native support for:

  • WebP;
  • AVIF.

The official PrestaShop 9 release information specifically highlights these formats as performance improvements.

Modern formats can reduce image transfer sizes significantly.

However, file format is only part of image optimization.

Also consider:

  • dimensions;
  • compression quality;
  • number of generated image types;
  • responsive images;
  • lazy loading;
  • CDN caching.

19. Remove Unused Image Types

Themes and modules can register multiple image sizes.

A large catalog can generate millions of files.

Example:

100,000 products
× 4 images
× 10 image types
= 4,000,000 generated files

If the current theme uses only six of those image types, four types may represent unnecessary storage and regeneration work.

Audit every image type before deleting anything.

Check:

  • theme templates;
  • modules;
  • email templates;
  • feeds;
  • marketplaces.

20. Do Not Serve Oversized Images

A product card displayed at 300 × 300 pixels should not download a 2000 × 2000 image.

The browser can visually resize it, but the customer still downloads and decodes the larger file.

Serve an image close to the rendered size.

This reduces:

  • bandwidth;
  • mobile data use;
  • decode time;
  • Largest Contentful Paint.

21. Lazy Load Below-the-Fold Images

Images that are initially outside the viewport do not always need to be fetched immediately.

Lazy loading can significantly reduce the initial network workload on:

  • category pages;
  • search results;
  • related-product carousels.

Do not lazy-load the primary Largest Contentful Paint image on a product page without testing.

The main hero image may need to load immediately.

22. Use Browser Caching

PrestaShop's current Nginx optimization documentation recommends configuring cache headers for static files.

Static assets such as:

  • CSS;
  • JavaScript;
  • fonts;
  • JPG;
  • PNG;
  • WebP;
  • AVIF;

can often be cached for long periods when URL versioning is reliable.

This reduces repeat traffic and speeds up navigation.

23. Compress Text Assets

Gzip or Brotli compression can reduce:

  • HTML;
  • CSS;
  • JavaScript;
  • JSON;
  • XML.

Image formats such as JPG, WebP and AVIF are already compressed and generally do not benefit meaningfully from generic gzip.

Configure compression at the web-server or CDN layer.

24. Use a CDN Where It Helps

A CDN is useful for:

  • images;
  • CSS;
  • JavaScript;
  • fonts.

It can improve latency for geographically distant customers and reduce load on the origin server.

But a CDN does not fix a 2-second PHP response.

Separate:

server generation time

from:

asset delivery time

when diagnosing performance.

25. Be Careful with Full-Page Caching

Full-page caching can be powerful, but ecommerce is personalized.

Content may vary by:

  • customer;
  • customer group;
  • cart;
  • currency;
  • language;
  • shop;
  • country;
  • tax rules.

A cache key that ignores those dimensions can show incorrect:

  • prices;
  • carts;
  • promotions;
  • customer data.

Do not sacrifice correctness for a benchmark score.

26. Redis Is a Tool, Not a Magic Switch

Redis can be useful for:

  • cache;
  • sessions;
  • queue state;
  • distributed locks.

But adding Redis to a badly designed module does not fix bad SQL.

If 80% of a page response is an expensive query, optimize that query first.

Use Redis when measurements show it solves a specific problem.

27. Optimize the Web Server

PrestaShop 9 documentation includes dedicated web-server optimization guidance.

Important areas include:

  • keep-alive;
  • HTTP/2 or newer protocol support;
  • compression;
  • cache headers;
  • connection limits;
  • logging overhead;
  • TLS configuration.

Nginx and Apache can both perform well.

Do not switch web servers purely because a forum post claims one is always faster.

28. Review Access Logging

Access logs are essential for debugging and security.

They also create I/O.

On very high-traffic stores, verbose logging of every static asset may generate unnecessary disk work.

Possible strategies include:

  • separate static logs;
  • buffering;
  • sampling where appropriate;
  • shorter retention;
  • disabling access logging for selected unimportant static assets.

Do not remove logs you need for incident investigation.

29. Move Heavy Imports Away from Peak Hours

If a large supplier import uses:

  • 80% CPU;
  • heavy database writes;
  • constant image processing;

then customers will feel it.

Schedule heavy jobs during lower traffic periods where possible.

If real-time synchronization is required, split the workflow into small continuous batches.

30. Use Locks for Cron Jobs

Duplicate cron execution can destroy performance.

A cron running every minute may launch another instance while the previous one is still active.

Use:

  • filesystem locks;
  • database leases;
  • Redis locks;
  • explicit job ownership.

A robust lock should expire or be recoverable after a crash.

Do not use a permanent boolean flag that can become stuck forever.

31. Separate Independent Cron Workflows

One global lock for every automation task can reduce throughput unnecessarily.

For example:

new product creation
stock update
price update
image download

may be independent.

If creation is blocked by an unmapped category, stock updates for existing products should still be able to run.

Define locking at the correct workflow level.

32. Monitor Queue Size

If a queue receives work faster than workers process it, the system is falling behind.

Monitor:

  • pending count;
  • retry count;
  • failed count;
  • oldest pending age;
  • processing rate.

A queue containing 50,000 items is not necessarily a problem if it processes 20,000 per hour.

A queue containing 500 items can be a serious problem if no item has moved for two days.

33. Use Bounded Retries

Retry temporary failures.

Examples:

  • supplier timeout;
  • HTTP 503;
  • temporary database deadlock.

Do not endlessly retry permanent validation failures.

Examples:

  • unknown category;
  • duplicate combination attribute set;
  • invalid required field.

After a threshold, move the item to a blocked or failed state.

This prevents broken records from consuming resources forever.

34. Optimize Search Separately

Search can have very different performance characteristics from normal product browsing.

Large catalogs may require:

  • optimized native search indexing;
  • dedicated search modules;
  • external search engines.

Do not install a large search platform unless the catalog and search behavior justify it.

Measure search latency and relevance separately.

35. Keep the Back Office Fast

Performance optimization is not only about customers.

A slow Back Office costs employee time.

Measure:

  • product page;
  • product grid;
  • orders;
  • stock pages;
  • module configuration;
  • bulk actions.

A custom module that adds a slow query to every order grid can create hundreds of lost work hours over a year.

36. Use Pagination Everywhere

Never render tens of thousands of records into one Back Office table.

Use:

  • pagination;
  • filters;
  • indexed sorting;
  • server-side queries.

Likewise, status pages should display summaries and recent items, not load the entire queue history.

37. Keep Dashboard Queries Cheap

Dashboards are opened frequently.

Do not calculate expensive lifetime statistics on every page load.

Precompute or cache:

  • totals;
  • daily aggregates;
  • recent failure counts.

An operational dashboard should answer questions quickly without becoming one of the largest database workloads.

38. Disable Debug Mode in Production

Developer mode is valuable during troubleshooting.

It should not remain enabled on a live store.

Development settings may:

  • reveal sensitive errors;
  • disable caching;
  • increase logging;
  • reduce performance.

Use production mode for normal operation.

39. Monitor Real User Performance

Synthetic tools are useful.

Real-user monitoring tells you what actual customers experience.

Track metrics by:

  • device;
  • country;
  • page type;
  • browser.

A desktop test on a fast connection may hide a slow mobile category page.

40. Build Performance Alerts

Set thresholds that matter to the business.

Examples:

  • product TTFB above 800 ms;
  • PHP-FPM queue above a threshold;
  • database CPU above 90% for five minutes;
  • disk free space below 15%;
  • cron job duration doubles;
  • import queue oldest item above one hour.

Alerts should lead to action.

Avoid alerting on every minor fluctuation.

Example PrestaShop 9 Optimization Workflow

A practical optimization project may look like this:

Phase 1 — Measure

Capture:

Homepage TTFB: 900 ms
Category TTFB: 1.8 s
Product TTFB: 1.2 s
Checkout TTFB: 800 ms

Phase 2 — Profile

Discover:

Category query: 900 ms
Module API call: 350 ms
PHP processing: 300 ms

Phase 3 — Fix largest bottleneck

Add an evidence-based database index.

New category TTFB:

650 ms

Phase 4 — Fix remote module call

Cache remote data for five minutes.

New category TTFB:

320 ms

Phase 5 — Optimize images

Reduce initial transferred image bytes by 40%.

Now the work has measurable evidence.

Example Large-Catalog Architecture

For a large automated store:

                        ┌──────────────┐
Customers ─────────────▶│ Nginx / CDN  │
                        └──────┬───────┘
                               │
                        ┌──────▼───────┐
                        │ PHP-FPM      │
                        │ PrestaShop 9 │
                        └──────┬───────┘
                               │
                     ┌─────────▼─────────┐
                     │ MySQL / MariaDB   │
                     └───────────────────┘

Background:
Supplier feed → Queue → Product workers
                         ├─ stock worker
                         ├─ price worker
                         └─ image worker

This separates interactive requests from heavy background work.

Performance Checklist

PHP

  • Supported PHP version
  • OPcache enabled
  • OPcache large enough
  • PHP-FPM workers measured
  • production mode enabled
  • web and CLI PHP versions verified

Database

  • slow-query log reviewed
  • expensive queries analyzed with EXPLAIN
  • indexes based on real workload
  • oversized history tables reviewed
  • large updates batched

Modules

  • global hooks profiled
  • remote calls removed from hot paths
  • unused modules removed
  • expensive dashboards cached

Images

  • WebP/AVIF enabled where appropriate
  • unused image types removed
  • responsive dimensions used
  • below-fold images lazy loaded
  • regeneration done through controlled jobs

Server

  • SSD/NVMe
  • sufficient free RAM
  • no swapping under normal load
  • compression enabled
  • browser cache headers configured
  • static asset CDN considered

Automation

  • cron jobs use locks
  • heavy jobs batched
  • queue health monitored
  • retries bounded
  • heavy work separated from customer traffic

Monitoring

  • HTTP latency monitored
  • PHP worker saturation monitored
  • database monitored
  • disk and inode usage monitored
  • cron duration monitored
  • alerts configured

Frequently Asked Questions

What is the fastest way to speed up PrestaShop 9?

Measure first. The highest-value fix is usually the largest real bottleneck, which may be SQL, a module, images, PHP-FPM saturation or a background job.

Does PrestaShop 9 support WebP and AVIF?

Yes. Native WebP and AVIF support was introduced with PrestaShop 9.

Which PHP version is best for PrestaShop 9?

The current official compatibility table recommends PHP 8.4 for PrestaShop 9.0 and PHP 8.5 for PrestaShop 9.1.

Will Redis make PrestaShop 9 faster?

It can help specific caching, session, queue or locking workloads. It does not automatically fix slow PHP or SQL.

Should I add more CPU cores?

Only when CPU is the bottleneck. If the database waits on slow storage or PHP waits on a remote API, more cores may provide little improvement.

Why is the store slow only during imports?

The import is probably competing with web traffic for CPU, RAM, database or disk I/O. Reduce concurrency, batch work, schedule differently or separate workers.

How do I speed up a 100,000-product store?

Focus on incremental imports, source hashes, indexed queries, bounded queues, image processing, database tuning and avoiding unnecessary product writes.

Is Nginx faster than Apache?

Both can perform well. Configuration and application behavior usually matter more than the server brand.

Should I clear the cache every hour?

No. Constantly invalidating useful caches can reduce performance. Invalidate only when needed.

How often should I review performance?

Continuously monitor key metrics and perform deeper audits after major releases, module changes, infrastructure changes or significant catalog growth.

Related PrestaShop 9 guides and resources

When performance symptoms are actually application failures

If slow or unstable requests end in intermittent 500 responses, use the production-safe HTTP 500 debugging workflow. Crash Snapshot Lite can capture supported application incidents without leaving full debug mode enabled.