[ GUIDE ]

Monitoring Laravel Livewire

Per-component performance, AJAX-storm avoidance, and the latency targets that make Livewire feel reactive instead of laggy.

QUICK ANSWER

How do I monitor Laravel Livewire components?

Every Livewire interaction is a POST to /livewire/update — a Livewire-heavy page fires 10-50 of these per user-minute. Standard APMs treat each as a separate request, flooding dashboards. Group by component class (extracted from the payload), target under 100ms p95 for simple actions and 300ms for complex ones, and watch for N+1 queries inside render() since it fires on every interaction. NightOwl captures every /livewire/update request; component-level aggregation is on the roadmap.

Updated · 2026-04-13

Why Livewire needs its own monitoring lens

Every user interaction — typing in a search box, clicking a checkbox, validating a field — is a POST to /livewire/update. A moderately interactive Livewire page can generate 10-50 backend requests per user-minute. That makes two things matter more than usual:

  • Per-component aggregation — per-route grouping is useless because every request hits the same route. You care which component is slow.
  • Latency targets — users expect UI to feel reactive. 300ms feels laggy; a normal HTTP request at 300ms feels fine.

Finding slow components

Your APM sees every Livewire interaction as a POST to /livewire/update. To find the slow ones, parse the request payload — it includes the component name:

Livewire 3 request shape (simplified)

json
{
  "components": [
    {
      "snapshot": {
        "memo": {
          "name": "app.products.filter-panel",
          "id": "abc123",
          ...
        },
        "data": { ... }
      },
      "updates": { ... },
      "calls": [{ "method": "updateFilter", "params": [...] }]
    }
  ]
}

Extract components[].snapshot.memo.name — that's the component class you want to group on.

Common Livewire performance bugs

N+1 inside render()

php
// Bad — render() fires on every interaction, each one refetches posts
public function render()
{
    return view('component', [
        'users' => User::all(),  // 1 query
        // Users->posts in template fires N queries per render
    ]);
}

// Good — eager-load
public function render()
{
    return view('component', [
        'users' => User::with('posts')->get(),
    ]);
}

Unbounded real-time search

php
// Bad — fires on every keystroke. 100 chars = 100 requests.
public $search = '';

// Good — debounce, wait for pause
// In Blade:
// <input wire:model.live.debounce.300ms="search">

// Better — only update on blur for expensive filters
// <input wire:model.blur="search">

Computed properties without caching

php
// Bad — recomputes on every render()
public function getCartTotalProperty()
{
    return $this->cart->items->sum('price'); // hits DB each time
}

// Good — memoize
use Livewire\Attributes\Computed;

#[Computed(cache: true, seconds: 5)]
public function cartTotal()
{
    return $this->cart->items->sum('price');
}

Latency targets

Interaction p95 target Feels laggy above
Toggle / checkbox< 100ms200ms
Form validation< 150ms300ms
Filter / search< 300ms500ms
Submit / save< 500ms1000ms

For interactions you can't get below 200ms, use wire:loading indicators — a visible spinner or disabled state masks the latency.

Instrumenting lifecycle events

app/Providers/AppServiceProvider.php

php
use Livewire\Livewire;

public function boot(): void
{
    Livewire::hook('component.mount', function ($component, $params) {
        logger()->info('Livewire mount', [
            'component' => $component::class,
            'params' => array_keys($params),
        ]);
    });

    Livewire::hook('component.boot', function ($component) {
        // Attach timing info, user context, etc.
    });
}

THE EASY WAY

NightOwl records every /livewire/update request

Filter to POST /livewire/update, sort by duration, find your slow interactions. Per-request trace drilldown shows which DB query or computed property ate the budget. Component-aware grouping is on the roadmap.

bash
composer require nightowl/agent
php artisan nightowl:install

Frequently asked questions

Why is Livewire monitoring different from regular Laravel requests?

Livewire components communicate via AJAX POSTs to /livewire/update. Every user interaction — a button click, input change, validation — is a round-trip to your server. A Livewire-heavy page can fire 10-50 requests per user-minute. Standard APMs treat each as a separate request, which floods dashboards with low-signal data. You want per-component aggregation, not per-request.

Can NightOwl group Livewire requests by component?

Yes, indirectly. The /livewire/update endpoint includes the component name in the payload; NightOwl captures the request and its route. You can filter to /livewire/update requests and see per-component performance. First-class Livewire-aware grouping (aggregating by component class, not endpoint) is on the roadmap.

How do I find slow Livewire components?

Filter your APM to POST requests against /livewire/update, then group by the component class in the payload. Look at p95 per component. Common slow components: real-time search (firing on every keystroke), filter panels (re-querying the full table), dashboards (multiple DB-heavy computed properties). Switch to on-blur or debounced updates where appropriate.

Does Livewire fire N+1 queries more than regular controllers?

Not inherently, but its reactive model hides them. A component's render() method fires on every interaction — if it lazy-loads a relationship inside the template, you're firing N+1 queries on every button click. Use computed properties with caching or pre-load relationships in mount() / boot().

How do I monitor Livewire lifecycle events?

Livewire dispatches events on mount(), hydrate(), updated(), render(). Hook in to log or instrument: Livewire::listen('component.booted', fn($component, $id) => ...). In Laravel 11+, the framework's Event dispatcher surfaces these. For production aggregation, push to an APM as custom spans or metrics.

What's the p95 target for a Livewire action?

Tighter than traditional requests because users expect immediate feedback. Under 100ms p95 for simple actions (toggle a checkbox); under 300ms for complex ones (filter update that re-queries). Above 500ms feels laggy. Use wire:loading indicators to mask any action you can't get below 200ms.

Does Livewire 3 change monitoring compared to Livewire 2?

Livewire 3 consolidated the wire format and moved to a single /livewire/update endpoint for all components (v2 had per-component endpoints in some setups). Grouping by URL is now less useful; you must parse the payload to get component context. Most APMs haven't fully caught up to v3's model yet.

PRICING

Flat pricing. No event caps. No per-seat fees.

14-day free trial, no credit card. Your PostgreSQL, your data.

HOBBY

$5 /month

1 app · 14 days lookback · all Laravel events

TEAM

$15 /month

Up to 3 connected apps · unlimited environments · all Laravel events

AGENCY

$69 /month

Unlimited apps · unlimited agent instances · same flat rate at any traffic

Related