A slow PrestaShop store can frustrate customers, hurt conversions, and affect your search performance. But before upgrading your hosting or removing modules, you need to understand what is actually causing the slowdown.
From server issues to database queries and module conflicts, several factors can affect store speed. Let’s explore how to identify the real cause and find the right solution.
Why A Slow PrestaShop Store Costs You More Than You Think
If your PrestaShop store feels sluggish, the temptation is to start flipping switches in the back office. That approach almost always wastes time and money.
A slow PrestaShop store is almost always caused by one dominant bottleneck: an unoptimised database, a misconfigured PHP or server environment, heavy third-party modules, or an un-cached theme. Find the real cause by measuring each layer in isolation, checking TTFB, query time, and rendering separately, rather than changing settings at random.
The cost of guessing is real. Aberdeen Group research found that 40 percent of shoppers abandon a website that takes more than three seconds to load, and PrestaShop merchants on the official forum have reported individual pages taking 13 to 15 seconds to serve the plain HTML. That is not a slow shop; that is a closed shop.
Random tweaking fails because your store is a stack, not a single thing. Four layers sit between a customer clicking a product and the page appearing:
- Server Layer: the hosting hardware, web server (Apache, Nginx, LiteSpeed) and how it handles concurrent requests.
- Database Layer: MySQL or MariaDB, and the speed at which it returns product, category and order queries.
- PHP Layer: the PHP version, OPcache configuration, memory limits and execution time.
- Theme & Front-end Layer: your template, the modules it loads, image sizes, CSS and JavaScript delivery.
A slow query and a slow module both produce a page that hangs, so you cannot tell them apart by staring at the storefront.
The only reliable method is measurement first. This article walks through how to test each layer individually, identify which one is actually holding your shop back, and fix the real cause instead of symptoms. You cannot fix a slow PrestaShop store until you have proven which layer is slow.
What You'll Need Before You Start
- Access Level: PrestaShop back office administrator, plus file access to config/defines.inc.php (FTP, SFTP or your hosting file manager).
- Database Access: a MySQL or MariaDB user able to run EXPLAIN queries, or a hosting support team willing to run them for you.
- PrestaShop Version: any currently supported 1.7 or 8.x release. PHP 7.4 or newer, with OPcache available.
- Tools: Google PageSpeed Insights, GTmetrix, browser developer tools, and optionally Xdebug with KCachegrind, QCachegrind or Webgrind.
- Environment: a staging copy of the shop, plus a full backup of files and database before any change.
- Estimated Time: roughly 60-90 minutes for a first full pass across five stages.
- Difficulty: moderate. You do not need to write code, but you will edit configuration files and read query output.
Why Diagnosing PrestaShop Slowness Matters
Every hour spent changing settings at random is an hour your shop stays slow and your customers keep leaving. PrestaShop has dozens of performance switches, and the vast majority address problems you may not have. Turning on caching when your database is the bottleneck hides the symptom for logged-out visitors and leaves the real cost untouched for everyone else.
Measurement also protects your revenue indirectly. Once you know your baseline TTFB, query count and template time, you can tell a hosting provider exactly what is wrong instead of upgrading a plan blindly.
Can You Fix PrestaShop Speed Without Guessing?
Yes. Measure each layer in isolation, confirm which one is slow, fix only that layer, then re-measure against the same baseline. PrestaShop's own profiler plus browser timing tools are enough to get a verdict, and a profiling module automates the collection if you would rather not run it by hand.
How To Diagnose A Slow PrestaShop Store Step by Step
Diagnosis starts with measurement, not configuration. Work through the five stages below in order. Each one tells you whether to keep digging or stop and fix what you have found.
Stage 1: Benchmark the Front Office Before You Change Anything
Run your homepage, a category page and a product page through Google PageSpeed Insights and GTmetrix, and record the numbers somewhere you can compare them later. Note the Time to First Byte (TTFB) separately, because TTFB isolates the server's response from everything the browser does afterwards.
The split matters. If TTFB is high but the page renders quickly once the response arrives, your bottleneck is server-side. If TTFB is low and the page still crawls, the problem is on the front end: images, JavaScript, or too many module assets loading on every page. Merchants on shared hosting sometimes report high response times on a clean install, which points at the hosting layer rather than PrestaShop itself.
If TTFB is fine and the page is still slow, stop looking at the server. You are chasing the wrong layer.
Stage 2: Turn On PrestaShop's Native Profiler
PrestaShop ships with a built-in profiling tool that most merchants never enable. In your shop's configuration file, set the profiling constant to true and switch the shop into debug mode. Clear the cache afterwards so the profiler picks up the current state.
Reload the slow page. PrestaShop now appends a profiling panel to the bottom of the page showing how long each controller took, which modules hooked into that request, and how long each database query ran. Sort the query list by duration.
- A single controller dominating the total points to code in that controller or an override attached to it.
- One module consuming most of the execution time means that module is the culprit, not PrestaShop core.
- Hundreds of short queries adding up suggest a query volume problem rather than one expensive statement.
Turn the profiler off when you are finished. Leaving debug mode active on a live shop exposes error details and slows every request.
Stage 3: Interrogate The Database
If the profiler shows database time as the dominant cost, take the slowest queries it reported and run them directly against your database with the EXPLAIN prefix. EXPLAIN tells you whether MySQL is using an index or scanning the entire table, and a full scan on a product or category table will not improve no matter how much memory you throw at PHP.
Next, check the slow query log on your database server. On shared hosting you may not have access, in which case ask your host to enable it or move to a plan where you control the database configuration. Look for queries that repeat on every page load. A missing index on a frequently filtered column is a common finding, and so is an overcrowded ps_connections or statistics table that has never been pruned.
Stage 4: Verify PHP Configuration
PHP settings are cheap to check and expensive to ignore. Confirm the PHP version your shop is actually running, not the one your hosting panel advertises. Newer PHP branches typically execute the same code faster, and PrestaShop performs noticeably better on a supported recent version than on an end-of-life one.
- OPcache: confirm it is enabled and that the memory allocation is large enough to hold your compiled files.
- memory_limit: raise it if your shop is hitting the ceiling during category or search pages, which forces repeated garbage collection.
- max_execution_time: if requests are timing out rather than returning slowly, this is a symptom, not a cause, so use the profiler to find what is taking so long.
Stage 5: Disable Overrides to Separate Theme From Core
PrestaShop lets modules and themes override core classes and templates. A single override can replace an efficient core method with a slower version, and tracing which one is responsible by reading code is slow work.
Switch to the default theme and disable overrides temporarily, then reload the same page and compare against your Stage 1 benchmark. If the page speeds up, your theme or an override is responsible. Re-enable them one at a time, checking the benchmark after each change, until the slowdown returns. The last thing you re-enabled is your answer.
| Symptom | Likely layer | Next check |
|---|---|---|
| High TTFB on every page | Server or hosting | Hosting plan, server resources |
| One controller shows most of the profile time | Override or module | Stage 5 override isolation |
| Profile shows hundreds of queries per page | Database | EXPLAIN on the slowest queries |
| Low TTFB but slow visual render | Front end or theme | Image sizes, module assets, theme |
| Random slow requests, not consistent | Server load or caching | Server logs, cache configuration |
Only once this table gives you a definite answer should you start changing settings. If you would rather automate the audit, PrestaShop profiling modules can collect the same controller, module and query timings for you.
Method 1: Using A Profiling & Performance Module to Pinpoint the Cause
Installing a profiling module turns guesswork into data. Instead of disabling features one at a time and hoping something improves, you get a per-page report showing where time is actually spent. That report tells you whether the bottleneck sits in the server, the database, PHP execution, or your theme and modules.
The PrestaShop Addons marketplace has a category of performance modules built specifically for this. A profiling module instruments each request and records the cost of every query, hook, and module call fired during that request.
Step 1: Install the Module From PrestaShop Addons
A profiling module has to be installed before it can instrument anything, and installing it on the wrong shop wastes the whole exercise. Work on staging so your baseline survives intact.
Go to PrestaShop Addons, open the performance category, and download the profiling module. In your back office, navigate to Modules -> Module Manager -> Upload a module, drag the ZIP archive in, and wait for PrestaShop to confirm the upload.
- Upload A Module: takes the ZIP file from your computer and installs it in one action. If your hosting restricts archive uploads, upload the extracted folder via FTP instead.
- Module Manager: lists every installed module and their version numbers, which is how you confirm the profiling module is actually active rather than merely uploaded.
- Enable: switches the module on. A profiling module usually does nothing until you enable it, so do not assume installation alone is enough.
Install the module on a staging copy first. Profilers add overhead, and you want that overhead on a shop you can restart freely.
Step 2: Configure the Profiling Options
The default settings decide how much detail you collect, and too much detail makes the report unreadable. Set the depth before you start collecting.
Open Modules -> Module Manager, find the profiling module, and click Configure. The settings page groups options by what they measure rather than by importance, so read each group before saving.
- Enable Profiling: the master switch. Nothing is recorded until this is on, and leaving it enabled permanently adds overhead to every visitor.
- Query Tracking: records each SQL statement with its duration and the calling context, which is what you use to find missing indexes.
- Hook and Module Timing: attributes execution time to the specific module attached to each display hook, so a heavy module becomes visible rather than blended into the total.
- Template and Controller Timing: separates Smarty rendering from controller logic, which tells you whether generation or presentation is slow.
- Report Retention: how long samples are kept before the module discards them, useful on busy shops where the table would otherwise grow quickly.
Step 3: Collect Samples on Your Heaviest Pages
Profiling the homepage alone hides the store's worst pages. Category listings with layered navigation and the checkout are usually the most expensive requests in a PrestaShop store.
Browse the shop as a customer would, starting with a category page that carries filters, then a product page, then the cart and checkout. Leave the module running long enough to capture several samples of each type.
- Category Pages: the heaviest requests in most shops because of faceted filters, price sliders and sorting.
- Product Pages: reveal per-product query patterns and any module that fires on every product view.
- Checkout and Cart: the pages where slowness costs money directly, so they deserve their own samples.
Step 4: Read the Report Top Down
The report only helps if you read it as a ranked list of costs rather than a wall of numbers. Open the module's dashboard, check the per-page summary first, then drill into the single slowest request.
| What the report shows | What it usually means | Where the fix lives |
|---|---|---|
| Total page generation time broken down by stage | One stage dominates the whole request | The layer that stage belongs to |
| List of executed SQL queries with duration | A handful of queries run far longer than the rest | Database indexes, or the module issuing them |
| Time attributed to each installed module | One module consumes a disproportionate share | That module's configuration or its replacement |
| Renderer and template time | Generation is fast, but the page still arrives late | Theme, caching, or the hosting stack |
Compare the same page type against itself rather than comparing a category page to a product page.
Step 5: Turn Profiler Output Into a Fix
A report that names no culprit is just overhead. Take the top entry from the report and match it to the fix below, then change only that one thing and re-profile the same URL.
- If one or two queries dominate, run EXPLAIN on them and check whether the columns in the WHERE clause are indexed, particularly id_productid_category and id_lang joins.
- If a single module owns a large slice of the runtime, disable it on a staging copy and re-profile the same URL. A drop confirms the module; no drop means you were looking at the wrong suspect.
- If module and query time are both low but the page still feels slow, the delay is outside PHP, so shift your attention to caching, image delivery, and the server itself.
If you cannot name the slowest layer in one sentence, you have not finished diagnosing, and every optimisation you apply from here is a coin flip.
On shared hosting, keep profiling runs short and outside peak trading hours, and disable the profiling module once you have your answer. Leaving a profiler active in production adds overhead and can expose query details you would rather not publish. If performance degrades again weeks later, reinstall it and compare against your recorded baseline.
Method 2: Manual Debugging and Code Profiling
A module gives you a fast verdict on which layer is guilty. Sometimes you need the raw evidence underneath that verdict, especially when the cause sits in custom code, a theme override, or an old module that no profiler label captures cleanly.
Because this method means touching live configuration and sometimes live files, work on a staging copy first and take a full backup of the database and files. Then follow the sequence below in order.
Step 1: Turn On Debug Mode and the Profiling Toolbar
PrestaShop ships its own diagnostics, but they stay hidden until you enable them. Turning them on is the only way to see the query count, template compile times, and hook timings per page.
- Open config/defines.inc.php and set _PS_MODE_DEV_ to true. The front office then shows every PHP notice, warning, and deprecation instead of swallowing them.
- In the same file, find the profiling constant and set it to true. PrestaShop renders a toolbar at the bottom of each page listing SQL queries, their duration, and the controller and template that fired them.
- Load the slow page, then read the toolbar from the top: controller execution, then Smarty template rendering, then the query list.
Never leave dev mode on in production, because it exposes file paths and error details to visitors.
Step 2: Read the Profiling Toolbar Like a Timeline
Total page time splits into controller time, template time, and query time, and the biggest block tells you where to dig next.
| Toolbar signal | What it usually means | Where to look next |
|---|---|---|
| One or two queries in the hundreds of milliseconds | Missing index or an unindexed custom column | MySQL slow query log and EXPLAIN |
| Hundreds of small queries from one controller | A loop calling the database once per product | The module or override that owns that controller |
| Template compile time on every request | Smarty recompiling because cache is disabled or template files keep changing | Smarty cache settings and file permissions |
| Hooks listed with long cumulative time | A heavy module attached to a display hook | Module list filtered by hook |
Write the three biggest numbers down before you change anything. This baseline is what proves later whether a fix actually worked.
Step 3: Catch Slow Queries with the MySQL Slow Query Log
The toolbar shows which queries are slow on the page you loaded. The slow query log covers the whole shop, which is how you find problems hiding on pages you never visit.
- Enable the slow query log in your MySQL or MariaDB configuration, set a threshold of around one second to start, and restart the database service.
- Browse the shop normally for a few minutes, including category pages, search results, and the checkout.
- Run EXPLAIN on the worst offenders to see whether MySQL is scanning a full table or using an index.
- Check for missing indexes on columns used in WHERE, JOIN, and ORDER BY clauses, and for tables that have grown far beyond the rest.
You should now have a short list of named queries with their execution plans, which you can hand to whoever owns the module or theme that generates them.
Step 4: Trace Hook Execution and Template Compilation
A single module hooked into a widely used display hook runs on every page, so its cost multiplies across your whole catalogue.
- Use the profiling toolbar's hook list to rank modules by cumulative time, then confirm by temporarily disabling one module at a time on staging and re-measuring the same page.
- Check the Smarty cache settings in Advanced Parameters -> Performance. Force compilation should be off and cache on, or PrestaShop rebuilds templates on every request.
- Clear the Smarty cache after any template edit so you are not measuring stale output, then re-run the page and compare against your baseline.
Step 5: Profile PHP Execution with Xdebug or Blackfire
PrestaShop's own toolbar stops at the framework boundary. A function-level profiler goes inside your custom code and shows exactly which function and which line burns the time, which is the only reliable way to judge code you or a previous developer wrote.
- Install Xdebug with the profiler enabled on staging only, load the slow page once, and open the generated cachegrind file in KCachegrind or QCacheGrind.
- Or install Blackfire and run a profile of the same page. Its call graph is easier to read when you are comparing two runs before and after a fix.
- Sort by inclusive time, then follow the call tree down to your own override or module class rather than stopping at the framework layer.
- Record the before-and-after profile for each change. A fix that does not move the numbers is not a fix.
Manual profiling beats a module when the bottleneck lives in code you own. Overridden controllers, custom modules, and third-party integrations rarely carry clean labels, and a function-level profile is the only tool that reads them directly. For stock shops with standard modules, the audit module covered in Method 1 will usually find the cause faster.
Troubleshooting: When the Numbers Still Don't Add Up
You have run the tests, read the timings, and the results contradict each other. A page returns quickly, then takes several seconds on the next refresh. Before you touch another setting, rule out the noise sources that mimic a real bottleneck.
Caching and CDN layers hiding the origin
A full-page cache serves the same HTML to everyone, so your profiling run never reaches the code you are trying to measure. Turn the cache off in PrestaShop under Advanced Parameters> Performance while you test, and clear it after each change. If you use Cloudflare or a similar CDN, enable development mode so requests bypass the edge and hit your server directly.
Test with the cache both on and off. A fast cached response paired with a slow uncached one tells you the origin is the problem, not the delivery layer.
Intermittent slowness from cron and shared hosting
Slowdowns that appear at the same hour every day are rarely caused by your theme. PrestaShop's cron tasks, catalog reindexing, and automatic backups all run on schedules and compete for the same CPU and disk. Check with your host whether the shop sits on shared resources, and confirm when your backup job fires.
On shared hosting, a neighbour saturating the disk can slow your store without any change on your side. If timings spike at unpredictable hours and recover on their own, ask your host to confirm the server was not under external load during those windows.
Third-party scripts creating false positives
Your browser's waterfall includes everything the page loads, not just PrestaShop's own output. Marketing pixels, chat widgets, review embeds, and analytics tags often account for a large share of total load time while your server responds perfectly.
Run the same page with those scripts blocked, or check the server response time separately from the full page load. If the server answers quickly and the page still takes much longer, you are chasing a front-end script, not a PrestaShop bottleneck.
A quick triage order
- Disable the cache and CDN, then re-test the same URL three times.
- Compare a cached response against an uncached one to separate origin from delivery.
- Log the time of day for each slow reading and match it against your cron schedule and backup window.
- Block third-party scripts and compare server response time against full page load time.
If your numbers cannot be reproduced twice in a row, you have not found a bottleneck yet; you have found noise.
| Symptom | Likely cause | What to check |
|---|---|---|
| Slow only on first visit | Origin or database | Uncached response time |
| Slow at fixed hours | Cron, backup, or indexing | Server task schedule |
| Server fast, page slow | Third-party scripts | External script tags |
| Random spikes, no pattern | Shared hosting load | Host resource report |
Once the readings hold steady across repeated tests, revisit the profiling data from your earlier runs and confirm the layer that keeps appearing at the top of the timeline.
Conclusion
PrestaShop slowness is never one thing. It is a chain: the web server responds, PHP builds the page, the database answers queries, the theme renders the template, and the browser paints the result. The chain is only as fast as its slowest link, and the only way to find that link is to measure each one instead of guessing.
Record a baseline first. Then split server time from application time, read PrestaShop's native profiler, interrogate the database with EXPLAIN, check PHP and OPcache, and isolate theme overrides one at a time until the slowdown returns. Only then change a setting, and change one at a time so you can prove it worked.
If the readings refuse to settle, the problem is noise, not architecture: a full-page cache, a CDN edge, a nightly cron job, or a third-party script. Rule those out before you blame PrestaShop. Once the numbers hold steady and the profiler names a layer, the fix is usually quick: an index, a module swap, a caching layer, or a hosting upgrade.
FAQ
How Do I Know Which Layer is Slowing Down My PrestaShop Store?
Measure before you change anything. Run your homepage, a category page and a product page through Google PageSpeed Insights and GTmetrix, and record TTFB separately from total load time. High TTFB points at the server, PHP or database; low TTFB with a slow render points at assets, modules or the theme. PrestaShop's native profiler then splits the server-side time further into controller, module and query cost.
Can I Profile A Live PrestaShop Shop Safely?
Not safely. Debug mode and profiling toolbars expose file paths, query details and error text to visitors, and profilers add overhead to every request. Run the audit on a staging copy with a full backup, then disable the profiler and debug mode as soon as you have your answer. A profiling module can be re-enabled later if performance regresses, so keep your baseline figures.
What is A Normal Number of Database Queries Per Page in PrestaShop?
It varies with your module count and theme, so there is no universal figure. What matters is the pattern: a product page running into four figures of queries, or one controller issuing hundreds of small queries in a loop, is an N+1 problem that no server upgrade will fix. Sort the profiler's query list by duration, then run EXPLAIN on the worst offenders to see whether MySQL is using an index.
Should I Use A Module or Manual Profiling?
A profiling module is faster for stock shops with standard modules, because it labels each module and hook automatically. Manual profiling with Xdebug, Blackfire or the MySQL slow query log earns its place when the cause sits in an overridden controller or custom code, since a function-level profile reads code that no module label captures cleanly.
Why is My PrestaShop Store Slow at the Same Time Every Day?
Scheduled work is the usual answer. PrestaShop's cron tasks, catalog reindexing and automatic backups compete for the same CPU and disk as customer traffic. Log the time of each slow read and match it against your cron schedule and backup window. On shared hosting, a neighbour saturating the disk can also slow your store without any change on your side, so ask your host to confirm.
Does Enabling PrestaShop's Cache Hide the Real Bottleneck?
It can. A full-page cache serves identical HTML to logged-out visitors, so your profiling run never reaches the code you are trying to measure, and the real cost still lands on logged-in customers and the checkout. Test with the cache both on and off, and if you use Cloudflare or a similar CDN, enable development mode so requests bypass the edge and reach your server directly.
How Often Should I Re-run This Audit?
Re-run it after any significant change: a new module, a theme update, a hosting migration, or a PrestaShop upgrade. The first pass takes roughly 60-90 minutes, and later passes are faster because you only need to re-measure against the baseline numbers you already recorded. If performance degrades weeks after a fix, reinstall the profiling module and compare against that baseline.