18 Jul 2026 · 2 min read
10 Magento 2 development mistakes that hurt performance
The recurring developer mistakes that quietly tank Magento 2 performance — from N+1 loads to plugin abuse and misconfigured caches — and how to avoid each.
Performance problems in Magento 2 rarely come from the platform itself. They come from small, repeated development decisions that compound. This post catalogs the ten we see most often — and the fix for each.
This series builds on the Magento 2 in practice intro, but stands on its own.
1. N+1 loads in collections
Loading a product, then looping and calling getX() that triggers another query per item. On a category page this becomes hundreds of queries.
Fix: use collection joins / addAttributeToSelect, eager-load relations once.
2. around plugins on hot paths
An around plugin wraps the original method and runs on every call — including product load in listings. Stack a few and TTFB climbs.
Fix: prefer before/after; use events when you don't need the return value.
3. Disabled or stale indexers
Leaving indexers on "Update on save" for large catalogs, or letting flat tables go stale, pushes read work into the request.
Fix: schedule indexers (or use the message queue); reindex before blaming the DB.
4. Cache disabled or misconfigured
Running with the full-page cache off, or with a leaky session cookie on every page, bypasses Varnish entirely.
Fix: verify FPC is on, sessions in Redis, and cacheable blocks aren't accidentally marked non-cacheable.
5. Loading the model when you need the resource
$product->load() inside a loop when a lightweight repository or collection query would do.
Fix: load collections, not entities, in bulk paths.
6. Heavy logic in templates (.phtml)
Business logic in templates runs on every render and can't be cached at the block level cleanly.
Fix: put logic in blocks/view models; keep templates presentational.
7. Over-fetching with GraphQL / REST
Requesting every field "just in case" in PWA/headless frontends balloons payloads.
Fix: query only the fields the view uses; batch where possible.
8. Unbounded result sets
->getItems() with no page size on large collections exhausts memory.
Fix: paginate; cap with setPageSize.
9. Ignoring the profiler
Shipping without ever looking at where time goes.
Fix: capture a profiler trace (the stock CSV profiler works well) and read it before optimizing blind.
10. Treating local as production
A dev machine with opcache off and no Varnish hides every caching win — then production surprises you.
Fix: run a production-shaped stack locally. A framework-aware orchestrator like Govard wires Varnish + Redis + OpenSearch so your local environment matches what you'll actually ship.
What's next in this series
We've named the mistakes; now the positive checklist. Next: the performance best practices that move the needle most.
Next in this series: Magento 2 performance best practices —
/blog/magento2-performance-best-practices