
To find the real bottleneck in a slow Magento 2 request, profile the exact request at the layer that hurts: the built-in Magento profiler for block, plugin, and observer timing, Blackfire or Xhprof for a full PHP call graph, and New Relic for production transaction traces and slow SQL. Then read exclusive time, not totals.
Most Magento performance work goes wrong at the first step. A page feels slow, someone clears the cache, bumps PHP memory, adds a Redis node, and the number barely moves. The fix for a slow request is almost never a guess. It is a measurement. The question is which tool measures the layer that is actually costing you time, and how to read the result so you change the one thing that matters instead of ten things that do not.
This guide walks through four profilers, when each one earns its place, and how to read a profile so the bottleneck is obvious. Bemeir builds and supports Magento and Adobe Commerce stores for a living, and this is the order we reach for these tools on a real slow-page ticket.
First, locate the slow layer before you profile anything
Profiling the wrong request wastes an afternoon. Before you attach a profiler, answer three questions.
Is it server time or browser time? Open the browser network panel and look at Time to First Byte for the document request. If TTFB is 200 ms and the page still feels slow, your problem is frontend render, not PHP, and a PHP profiler will show you nothing useful. If TTFB is 1.5 seconds, the server is building the response slowly and a PHP profiler is exactly right. Our walk-through of the usual suspects behind a slow Magento store covers the frontend side in depth.
Is the page cached? Magento serves most catalog and CMS pages from full-page cache. A cached hit never runs the controllers, blocks, and database queries you want to measure. Profile a cache MISS on purpose. Append a unique query string, or profile a logged-in session, or hit a page type that is never cached, such as cart or checkout.
Which request, exactly? “The site is slow” is not a request. “Category page with 48 products, logged out, cache miss, 1.8s TTFB” is. Pin the single URL and state before you touch a tool.
The built-in Magento profiler: the cheapest first look
Magento ships a profiler built on Magento\Framework\Profiler, and it is the fastest way to see where server time goes without installing anything. Per Adobe’s configuration guide, you enable it two ways. The command line route is bin/magento dev:profiler:enable html, which writes a flag file and renders a timing table in the page footer; csvfile writes the same data to a file instead. You can also set the MAGE_PROFILER environment variable, where a value of 1 selects an output driver and 2 adds dependency graphs. Turn it off with bin/magento dev:profiler:disable.
What it shows is a nested timer tree: how long each block rendered, how long observers for an event took, the time spent in specific plugins, and how often each was called. That is often enough to answer “which block or which module is eating the request” in five minutes. If one third-party block shows 900 ms of a 1.4s page, you have your suspect.
Its limits matter. It only times what the framework instruments, so a slow raw SQL query or a slow external API call hides inside a block’s total rather than showing up on its own line. It adds overhead, so the absolute numbers run high. Treat it as a pointer to the guilty layer, not as a precise stopwatch, and never leave it enabled in production.
Blackfire: the full PHP call graph, on demand
When the built-in profiler points at a layer but not a root cause, Blackfire gives you the complete picture. It instruments PHP automatically and builds a call graph of every function in the request.
The design point that makes it safe for production is that, as Blackfire’s own documentation puts it, it never instruments real-user requests. It profiles only when an authorized user triggers it, through the CLI or the browser extension, so it adds no overhead to normal traffic. For each function call it reports wall-clock time, CPU time, and I/O time, which lets you tell a CPU-bound slowdown from one that is waiting on the database or a web service. Because time measurements can be unstable from run to run, it also reports metrics that do not depend on time, such as memory usage and SQL query counts.
Setup is a PHP probe extension plus the Blackfire agent, then the CLI or Chrome extension to trigger a profile. On a Magento server you load the probe in php.ini, point it at the agent socket, and restart PHP-FPM. From there you run blackfire curl against a URL or click the extension on a page.
The real skill is reading the graph, which the next section covers. Blackfire’s comparison mode is the part teams underuse: profile before a change and after, and it draws the delta so you can prove a fix actually moved the number instead of hoping it did.
Xhprof: the free, self-hosted profiler
Blackfire is a paid service. When budget or a client’s data-residency rules rule it out, Xhprof gives you a hierarchical PHP profile for free. The modern path on Magento 2 is the Tideways Xhprof PHP extension plus a module that wires it into the request lifecycle.
The justbetter/magento2-xhprof-profiler package on Packagist does this cleanly and supports Magento 2.4.4 through 2.4.8. It adds a storefront toolbar and an admin profiler that trace every block render, observer, plugin, layout phase, dependency injection resolution, and database query in a single request. That is close to Blackfire’s breakdown for the cost of a Composer install, with the trade-off that you read the output yourself rather than in a hosted call-graph UI, and the extension overhead is heavier so you run it in a development or staging context, not under live traffic.
New Relic: catching what only breaks in production
Some slowdowns never reproduce on a developer laptop. They happen at 11 a.m. under real traffic, with a cron consumer running, a real catalog size, and a specific customer group. For those you need always-on production instrumentation, and New Relic APM is the standard choice for Adobe Commerce.
Adobe ships a New Relic Reporting module. On the Pro tier of Adobe Commerce on Cloud it is preconfigured and enabled; on Starter and self-hosted you add your account and application credentials under Stores, Configuration, General, New Relic Reporting. Once it reports, the APM UI gives you transaction traces, an Apdex score per transaction, and database query monitoring.
The feature that earns its keep on a slow-page investigation is slow SQL sampling. As New Relic’s documentation explains, when a transaction trace is captured, New Relic samples the slowest queries in it and surfaces them on the Databases page with their durations and, where available, explain plans. So you can open a slow checkout transaction, see that one catalog_product_entity query ran for 600 ms, and know exactly where to look. One caveat for cloud projects: Adobe Commerce on Cloud cannot send data from external servers into its provisioned New Relic account, so only work the application itself invokes is traced. Our observability and APM playbook goes deeper on standing up this layer for an enterprise store.
Reading a profile: exclusive time, call counts, and the N+1 trap
Every tool above produces more data than you need. Three habits turn a profile into an answer.
Sort by exclusive time, not inclusive. Inclusive (or total) time for a function includes everything it called. The top of that list is always your framework entry point, which is useless. Exclusive (self) time is the time spent in that function alone. Sort by exclusive time and the real hotspot rises to the top, whether that is a pricing calculation, a layout render, or a serialization call.
Watch the call count column. A function that takes 2 ms is fine. A function that takes 2 ms and is called 3,000 times in one request is a 6-second problem, and it almost always means a loop is doing something it should do once. This is where slow third-party extensions hide, as practitioners note: group the call graph by vendor namespace and the module making 3,000 calls is obvious.
Look for the N+1 query pattern. The single most common Magento bottleneck is code that loads a collection, then issues one more query per row instead of joining or batching. A profile shows it as the same query signature repeated hundreds of times, each one fast, together catastrophic. The fix is a single query or a preloaded map, and the re-profile proves it. Admin grids and report pages are repeat offenders; our guide to why the Adobe Commerce backend goes slow catalogs the admin-side versions.
If the slow query turns out to be a reindex or a cron queue backing up rather than a single request, that is a different investigation, and cron and indexer health is the right starting point.
Which profiler for which job
| Tool | Where it runs | Overhead | Best for | Cost |
|---|---|---|---|---|
| Built-in Magento profiler | Dev or staging | Moderate | First look at which block, plugin, or observer is slow | Free |
| Blackfire | Dev, staging, or on-demand in production | None when idle | Full PHP call graph with CPU, I/O, SQL counts, and before/after comparison | Paid (free tier limited) |
| Xhprof (Tideways extension) | Dev or staging | Heavy | Free, self-hosted call graph when a paid service is off the table | Free |
| New Relic APM | Production | Low, always on | Slowdowns that only appear under real traffic, plus slow SQL sampling | Paid |
The pattern that works: start with the built-in profiler to find the layer, confirm the root cause with Blackfire or Xhprof on a reproduced request, and keep New Relic running so production-only regressions surface before a customer reports them.
A repeatable workflow that actually closes the ticket
- Reproduce one exact request and record its baseline TTFB on a cache miss.
- Run the built-in profiler to find the slow layer.
- Profile the same request with Blackfire or Xhprof and sort by exclusive time.
- Change one thing. Not three. One.
- Re-profile the identical request and compare against the baseline.
- If the number moved, ship it and watch New Relic for the regression. If it did not, revert and go back to step 3.
Changing one variable at a time is what separates a measured fix from a superstition. It is slower for the first hour and much faster over the life of the project.
Performance is the reason most merchants come to a specialist in the first place, whether the store runs on Magento, Shopify, Shopware, or BigCommerce. As the first US-based Hyva development partner, much of our work pairs a faster frontend with a backend that answers quickly, and the tools above are how we prove the backend half. The monitoring and profiling stack also draws on our technology partner ecosystem, since the right APM and tracing tools are part of building something fast enough to sell against.
If your team is staring at a slow page and guessing, that is the signal to profile instead. Bemeir helps Magento and Adobe Commerce teams find and fix the real bottleneck, and you can learn more about Bemeir and how we work.
FAQ
Why does my Magento page look fast in a profiler but slow for real users?
The profiler is likely hitting a cached response or running on a faster machine than production. Profile a cache miss, on a box sized like production, with a real catalog, and the slow path reappears. For issues that only show under concurrent load, you need always-on production monitoring such as New Relic rather than a one-shot profile.
Is it safe to run Blackfire on a production store?
Yes, within its design. Blackfire does not instrument normal traffic and only profiles a request when an authorized user triggers it, so it adds no overhead to real customers. Many teams keep the probe installed in production precisely so they can profile a slow page in the environment where it actually breaks.
What is the difference between exclusive and inclusive time in a profile?
Inclusive time for a function counts everything it called beneath it, so top-level entry points always dominate that list. Exclusive, or self, time counts only the work done inside that function. Sorting by exclusive time points you at the real hotspot instead of the framework scaffolding above it.
Do I need a paid profiler, or is Xhprof enough?
Xhprof with the Tideways extension gives you a full hierarchical profile for free and is enough for most root-cause work in development and staging. The paid tools add convenience: Blackfire’s hosted call graph and before/after comparison, and New Relic’s always-on production tracing. Many teams run free Xhprof locally and a paid APM in production.
Where should I start if I have never profiled a Magento request?
Start with the built-in profiler. Enable it with bin/magento dev:profiler:enable html, load one slow page on a cache miss, and read the footer timing table. It costs nothing to try and usually points you at the slow module within minutes, which tells you whether you need a deeper tool next.





