PrestaShop performance: caching a dynamic shop the right way
PrestaShop gives you a serious shop out of the box, and a serious amount of work per page to go with it. How to make it fast without breaking the dynamic bits.
PrestaShop assembles each page from PHP, Smarty templates and a busy database, which is why big catalogues get sluggish. Cache the catalogue β home, categories, products β at the edge, and bypass the cache whenever PrestaShop's session cookie is present so carts, checkout and customer accounts stay live. Watch out for multi-currency and multi-language shops, which need the cache key to include those dimensions.
PrestaShop is a proper ecommerce platform: multi-store, multi-currency, multi-language, and a module ecosystem that will happily let you install thirty things. All that capability has a cost, and the cost usually shows up once the catalogue passes a few hundred products and someone asks why the category pages take two seconds.
Where the time goes
Every PrestaShop page is assembled on demand. PHP boots, the Smarty template engine renders, modules run their hooks, and the database is queried β often heavily, because layered navigation, price rules, stock and combinations all have to be resolved before the page can be drawn.
The specific things that tend to hurt, in roughly the order they appear as a shop grows:
- Layered navigation on large categories. Faceted filtering is expensive, and the queries grow with your attribute count.
- Product combinations. A product with five sizes and six colours is thirty combinations to resolve, each with its own price and stock.
- Specific price rules. Every price shown may need catalogue price rules evaluated against the current customer group, currency and country.
- Module hooks running on every page. Modules register hooks that fire whether or not the page uses them, and nobody audits them.
- Image regeneration. Thumbnail regeneration after a theme change is a well-known way to occupy a server for hours.
None of this is a defect. It is what makes PrestaShop capable. It is just work being repeated for every visitor, including the thousandth visitor to a product page that has not changed since March.
The split that makes caching safe
| Page | Cache it? | Note |
|---|---|---|
| Homepage, categories, product pages | Yes | The bulk of your traffic |
| CMS pages, manufacturer and supplier lists | Yes | Rarely change |
| Search results | Usually | Short TTL; normalise the query parameter |
| Layered navigation results | Carefully | Cacheable, but watch the number of filter combinations |
| Cart and checkout | Never | Personal by definition |
| My Account, order history, addresses | Never | Personal data |
| Anything under the admin folder | Never | Bypass entirely |
Getting the bypass right
The whole trick is recognising when a visitor is "in session" rather than just browsing. PrestaShop sets a session cookie β named PrestaShop- followed by a hash unique to your installation β once a shopper has a cart or logs in. Bypass the cache whenever that cookie is present, and everything works: anonymous browsers get cached pages, anyone with a cart gets a live one.
Two details that catch people out:
Do not bypass on the cookie merely existing in some form. Some configurations set a session cookie on first visit regardless of activity, which would mean nobody ever gets a cached page and your hit ratio sits near zero while you wonder what went wrong. Check whether your installation issues that cookie to anonymous visitors before relying on its presence.
Strip the tracking parameters. PrestaShop shops attract a lot of campaign traffic, and ?utm_source= variants fragment your cache badly. Remove them from the cache key.
The multi-currency and multi-language trap
This one is specific to PrestaShop and it is worth more attention than it usually gets, because getting it wrong shows a Danish shopper prices in euros β or worse, shows a wholesale customer group retail prices.
PrestaShop resolves language, currency and customer group per request, frequently from cookies. If your cache key does not include those dimensions, the first visitor to request a page fills the cache with their version and everyone after that receives it.
The fix is either to include the relevant cookies in the cache key β so each currency and language gets its own cached copy β or to use distinct URLs per language and currency, which is better for SEO anyway. Multi-shop installations need the shop dimension in the key too.
Test this deliberately before going live. Open the shop in one browser, switch currency, then open it in a fresh incognito window and check which currency you get. It takes ninety seconds and it catches the single most damaging caching mistake a PrestaShop can make.
Purging when things change
A cached catalogue needs invalidating when the catalogue changes. Price updates, stock changes and new products all need the affected pages purged, or shoppers see yesterday's prices β which is a customer-service problem and, depending on where you trade, potentially a legal one.
Practical approach: purge the specific product URL and its category pages on product save, purge broadly after a bulk import, and keep product page TTLs modest β an hour rather than a day β so anything a purge misses corrects itself quickly. If you display live stock counts, either exclude that fragment from the page or accept that stock display lags your TTL.
And the images
A PrestaShop store lives and dies on product photography, and image weight is usually the largest single component of page size. Converting to WebP or AVIF and resizing at the edge routinely does more for perceived speed than any backend tuning β and unlike regenerating thumbnails in the admin panel, it does not need an hour of server time and a prayer.
Frequently asked questions
Why is my PrestaShop site slow?
Because every page is assembled on demand from PHP, Smarty templates and database queries, and that work repeats for every visitor. The load grows with the catalogue: layered navigation, product combinations, specific price rules and module hooks all add queries per page. Caching the pages that are identical for all shoppers removes the repetition rather than optimising it.
Can I use full-page caching with PrestaShop?
Yes, for the catalogue. Homepage, category, product and CMS pages are identical for anonymous visitors and can be cached at the edge. Cart, checkout, customer account pages and the admin area must always bypass the cache, which is handled by detecting PrestaShop's session cookie and serving those visitors a live page.
Which PrestaShop cookie should trigger a cache bypass?
The PrestaShop session cookie, named PrestaShop- followed by a hash unique to your installation. Its presence indicates the visitor has a cart or is logged in, and the cache should be bypassed for those requests. Verify first whether your installation issues that cookie to anonymous visitors on first page load, since if it does, bypassing on its presence alone would prevent any page from ever being cached.
How do I cache a multi-currency PrestaShop shop?
Include currency and language in the cache key, either by adding the relevant cookies to the key so each combination is cached separately, or by using distinct URLs per language and currency, which is preferable for SEO. Without this, the first visitor to request a page fills the cache with their currency and every subsequent visitor receives it. Multi-shop installations must include the shop dimension as well.
How do I stop customers seeing outdated prices from the cache?
Purge the affected product and category URLs whenever a product is saved, purge broadly after bulk imports, and keep product page TTLs to around an hour so anything a purge misses self-corrects quickly. If you display live stock levels, either exclude that fragment from the cached page or accept that it will lag by the length of the TTL.
The summary is that PrestaShop is heavy for good reasons and cacheable for better ones. Cache the catalogue, bypass on the session cookie, get currency and language into the cache key before you go live, and optimise the photography. You keep every bit of the platform's capability and lose the part where it makes people wait.
See how NordicCDN does this for your site:
Mads has worked in IT β mostly hosting β since he was 16. He took an early stake in a SaaS company and helped grow it through to its acquisition by Visma, has built and run data-center networks, and served as CTO of a Danish data center. He started NordicCDN to make fast, secure infrastructure simple to use.