Profiling Laravel with Blackfire and Xdebug | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com) [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles  ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

  [ home ](https://msaied.com)    [ articles ](https://msaied.com/articles)    Profiling Laravel with Blackfire and Xdebug: Finding Real Bottlenecks        On this page       1. [  Stop Guessing, Start Measuring ](#stop-guessing-start-measuring)
2. [  Xdebug: Callgrind Profiles for Local Investigation ](#xdebug-callgrind-profiles-for-local-investigation)
3. [  Enable profiling on demand ](#enable-profiling-on-demand)
4. [  What to look for in Laravel ](#what-to-look-for-in-laravel)
5. [  Blackfire: Continuous Performance Assertions ](#blackfire-continuous-performance-assertions)
6. [  Install and profile via CLI ](#install-and-profile-via-cli)
7. [  Writing performance tests (Blackfire Builds) ](#writing-performance-tests-blackfire-builds)
8. [  A Practical Workflow ](#a-practical-workflow)
9. [  Step 1 — Reproduce with Xdebug locally ](#step-1-reproduce-with-xdebug-locally)
10. [  Step 2 — Confirm with Blackfire on staging ](#step-2-confirm-with-blackfire-on-staging)
11. [  Step 3 — Fix one thing at a time ](#step-3-fix-one-thing-at-a-time)
12. [  Step 4 — Gate it in CI ](#step-4-gate-it-in-ci)
13. [  Takeaways ](#takeaways)

  ![Profiling Laravel with Blackfire and Xdebug: Finding Real Bottlenecks](https://cdn.msaied.com/473/5b2261450fb7c3c68870997e338c2e1b.png)

  #laravel   #performance   #profiling   #blackfire   #xdebug  

 Profiling Laravel with Blackfire and Xdebug: Finding Real Bottlenecks 
=======================================================================

     26 Jul 2026      4 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

  13 sections  

1. [  01   Stop Guessing, Start Measuring  ](#stop-guessing-start-measuring)
2. [  02   Xdebug: Callgrind Profiles for Local Investigation  ](#xdebug-callgrind-profiles-for-local-investigation)
3. [  03   Enable profiling on demand  ](#enable-profiling-on-demand)
4. [  04   What to look for in Laravel  ](#what-to-look-for-in-laravel)
5. [  05   Blackfire: Continuous Performance Assertions  ](#blackfire-continuous-performance-assertions)
6. [  06   Install and profile via CLI  ](#install-and-profile-via-cli)
7. [  07   Writing performance tests (Blackfire Builds)  ](#writing-performance-tests-blackfire-builds)
8. [  08   A Practical Workflow  ](#a-practical-workflow)
9. [  09   Step 1 — Reproduce with Xdebug locally  ](#step-1-reproduce-with-xdebug-locally)
10. [  10   Step 2 — Confirm with Blackfire on staging  ](#step-2-confirm-with-blackfire-on-staging)
11. [  11   Step 3 — Fix one thing at a time  ](#step-3-fix-one-thing-at-a-time)
12. [  12   Step 4 — Gate it in CI  ](#step-4-gate-it-in-ci)
13. [  13   Takeaways  ](#takeaways)

       Stop Guessing, Start Measuring
------------------------------

Most Laravel performance work starts with a hunch: "It's probably an N+1" or "The cache must be cold." Hunches waste time. A profiler shows you the exact call stack, wall time, and memory allocation for every microsecond of a request. This article covers a practical workflow using both Xdebug (for local deep dives) and Blackfire (for CI and staging gates).

---

Xdebug: Callgrind Profiles for Local Investigation
--------------------------------------------------

Xdebug's profiler writes Callgrind-format files that tools like QCacheGrind or PhpStorm's built-in viewer can parse.

### Enable profiling on demand

Avoid always-on profiling — it tanks throughput. Use the trigger approach:

```ini
; php.ini / xdebug.ini
xdebug.mode = profile
xdebug.start_with_request = trigger
xdebug.output_dir = /tmp/xdebug
xdebug.profiler_output_name = cachegrind.out.%R.%t

```

Then trigger a profile with a cookie or query string:

```bash
curl -b 'XDEBUG_PROFILE=1' https://local.app/api/reports/summary

```

Open the resulting file in QCacheGrind and sort by **Self Cost**. You're looking for functions that consume time *themselves*, not just because they call expensive children.

### What to look for in Laravel

- `Illuminate\Database\Connection::select` appearing hundreds of times → N+1
- `Illuminate\Container\Container::resolve` with high self cost → over-resolved singletons or missing `singleton()` bindings
- `Illuminate\Routing\Router::runRouteWithinStack` with deep middleware chains → middleware doing redundant work per request

---

Blackfire: Continuous Performance Assertions
--------------------------------------------

Blackfire's agent instruments PHP at the C extension level with negligible overhead (~1–3 %), making it safe for staging and even canary production traffic.

### Install and profile via CLI

```bash
blackfire run php artisan tinker --execute="app(App\Services\ReportBuilder::class)->build(1);"

```

Or profile an HTTP request:

```bash
blackfire curl https://staging.app/api/reports/summary

```

Blackfire's web UI shows a flame graph with **exclusive time** per node — identical concept to Xdebug's self cost, but interactive and shareable.

### Writing performance tests (Blackfire Builds)

Blackfire Builds let you assert performance budgets in CI:

```yaml
# .blackfire.yaml
tests:
  "Report summary endpoint":
    path: /api/reports/summary
    assertions:
      - "main.wall_time < 300ms"
      - "main.peak_memory < 20mb"
      - "metrics.sql.queries.count < 10"

```

The `metrics.sql.queries.count` assertion is the cleanest way to enforce N+1 prevention in a pipeline — no custom middleware, no test doubles.

---

A Practical Workflow
--------------------

### Step 1 — Reproduce with Xdebug locally

Get the Callgrind file, identify the top three self-cost offenders. Don't fix anything yet.

### Step 2 — Confirm with Blackfire on staging

Blackfire's timeline view shows *when* in the request lifecycle each call happens. A slow `boot()` in a service provider shows up clearly here — it fires before your controller even runs.

### Step 3 — Fix one thing at a time

Common fixes and how to verify them:

```php
// Before: resolved fresh every call inside a loop
foreach ($ids as $id) {
    $result = app(TaxCalculator::class)->calculate($id);
}

// After: bind as singleton so the container returns the same instance
$this->app->singleton(TaxCalculator::class);

```

After each fix, re-run the Blackfire CLI comparison:

```bash
blackfire curl --reference 1 --samples 5 https://staging.app/api/reports/summary

```

Blackfire's comparison view highlights regressions in red and improvements in green — no mental arithmetic required.

### Step 4 — Gate it in CI

Add the `.blackfire.yaml` assertions to your GitHub Actions or GitLab CI pipeline. A PR that introduces a new N+1 fails the build before it reaches production.

---

Takeaways
---------

- Use **Xdebug trigger mode** locally to avoid always-on overhead; sort by self cost, not inclusive cost.
- **Blackfire's `metrics.sql.queries.count`** assertion is the most reliable CI guard against N+1 regressions.
- High `Container::resolve` self cost usually means missing `singleton()` bindings or service providers doing work in `register()` that belongs in `boot()`.
- Profile *before* optimizing — the bottleneck is almost never where you expect it.
- Blackfire comparisons between two runs give you objective proof that a fix worked, not just a feeling.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Fprofiling-laravel-with-blackfire-and-xdebug-finding-real-bottlenecks-1&text=Profiling+Laravel+with+Blackfire+and+Xdebug%3A+Finding+Real+Bottlenecks) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Fprofiling-laravel-with-blackfire-and-xdebug-finding-real-bottlenecks-1) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  Can I use Blackfire and Xdebug at the same time?        No. Both are PHP extensions that instrument the Zend engine, and they conflict when loaded simultaneously. Use Xdebug for local Callgrind profiles and Blackfire for staging/CI assertions — switch between them by toggling which extension is active in your php.ini or Docker image. 

      Q02  Does Blackfire work with Laravel Octane?        Yes, but with caveats. Because Octane keeps the application bootstrapped between requests, Blackfire profiles will not include the service provider boot phase after the first request. Profile the first cold request separately to capture bootstrap cost, then profile subsequent warm requests for steady-state performance. 

      Q03  What is the difference between inclusive and exclusive (self) time in a profiler?        Inclusive time is the total time spent in a function including all its callees. Exclusive (self) time is only the time spent in the function body itself. For finding real bottlenecks, sort by self time — a function with high inclusive time may simply be your main controller calling many fast helpers, while a function with high self time is genuinely doing expensive work. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://msaied.com/articles) 

 [ ![Filament v4 Migrating from v3: Breaking Changes and Refactor Patterns](https://cdn.msaied.com/472/bb7fbf8441c775fcfadd23850e1756e8.png) filament laravel migration 

### Filament v4 Migrating from v3: Breaking Changes and Refactor Patterns

A practical, opinionated guide to the most impactful Filament v3→v4 breaking changes: schema-based forms, the...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 26 Jul 2026     4 min read  

  Read    

 ](https://msaied.com/articles/filament-v4-migrating-from-v3-breaking-changes-and-refactor-patterns) [ ![Concurrency in Laravel: Process Pools, Fibers, and the Concurrency Facade](https://cdn.msaied.com/471/ba1a628c196e92cbb81033c865c9ad26.png) laravel concurrency php 

### Concurrency in Laravel: Process Pools, Fibers, and the Concurrency Facade

Laravel's Concurrency facade and process pools let you run independent work in parallel without reaching for a...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 26 Jul 2026     4 min read  

  Read    

 ](https://msaied.com/articles/concurrency-in-laravel-process-pools-fibers-and-the-concurrency-facade) [ ![Laravel Queues in Production: Horizon Tuning, Metrics, and Graceful Scaling](https://cdn.msaied.com/470/afd2bee56d15842d72c1c6d5c238d236.png) laravel horizon queues 

### Laravel Queues in Production: Horizon Tuning, Metrics, and Graceful Scaling

Go beyond basic queue setup. Learn how to tune Horizon supervisor processes, interpret queue metrics, handle b...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 26 Jul 2026     3 min read  

  Read    

 ](https://msaied.com/articles/laravel-queues-in-production-horizon-tuning-metrics-and-graceful-scaling) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://msaied.com)
- [Projects](https://msaied.com/projects)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/certificates)
- [Contact](https://msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
