Livewire computed properties: automatic caching and payload reduction
Livewire's #[Computed] attribute lets you derive values that are evaluated once per request and sent only as rendered output, cutting frontend payload and eliminating redundant calculations.
07 Jul 2025, 05:09 UTC

The problem and the useful takeaway
You reference a derived value like a total, a filtered count, or a pagination offset multiple times inside a Livewire component. Without computed properties each reference can re-execute the underlying logic or trigger another database query, especially if the value depends on public state that changes between requests.
The useful answer: declare the value as a computed property. Livewire evaluates it once per request cycle and caches the result. Every {{$this->propertyName}} in your Blade view pulls the cached value, and only the rendered output—not the property definition—gets sent to the browser.
How it works in Livewire v3
Livewire v3 introduced the #[Computed] attribute. Mark a method with it and Livewire will:
- Execute the method once per HTTP request
- Store the result internally, accessible via
$this->propertyName - Render only the value in the Livewire snapshot; the attribute name never reaches the frontend
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Post;
class PostSearch extends Component
{
public string $query = '';
#[Computed]
public function resultCount()
{
return Post::where('title', 'like', '%' . $this->query . '%')->count();
}
public function render()
{
return view('livewire.post-search');
}
}
What the frontend actually receives
Because resultCount is a computed property, Livewire does not include a resultCount key in the JSON payload sent to the browser. Instead the final count number appears wherever the Blade template renders it. This contrasts with a public property, which Livewire tracks as a reactive field and includes in the snapshot even when unchanged.
Concrete comparison: payload size
Imagine a component that defines a public $totalItems array and a computed $totalItemsSum that sums it. After several user interactions the Livewire network tab shows:
- Public property: the snapshot contains
totalItemsregardless of whether the view uses it. - Computed property: the snapshot contains no
totalItemsSumkey; only the rendered number appears in the DOM.
In practice this means computed properties keep the initial payload smaller and reduce the amount of data transmitted on each poll.
Limits and common mistakes
- Side effects: Computed properties should be read-only. Avoid writing to a database or modifying external state inside a
#[Computed]method. - Version mismatch: The
#[Computed]attribute is Livewire v3 only. Livewire v2 requires thegetPropertyNamenaming convention and does not offer the same automatic caching behavior. - Over-reliance for heavy calculations: If a computed property performs complex logic on every request without external caching (e.g., Redis), high-traffic pages can still experience latency.
- Assuming cross-request reactivity: The cache resets each new HTTP request. If you need the value persisted across sessions, store it in session storage or a database.
Quick verification steps
- Add a
Log::debug()ordd()inside the computed method. Reload the page multiple times while referencing the property in the view. The log should appear exactly once per request. - Open the Network tab and inspect the Livewire XHR response. Confirm the computed property’s key is absent from the JSON; only its rendered value influences the DOM.
- Change the public dependency (e.g., the query) and submit. The view should reflect the new computed value on the next request, confirming reactivity.
Livewire computed properties are a pragmatic tool for deriving values from existing component state without paying the cost of repeated evaluation or bloated frontend payloads. Use them for filtering, aggregating, or pagination-derived numbers, and keep them side-effect-free to stay within the intended design.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.