Inertia Live Props: Real-Time Pages With Laravel Reverb
Table of contents
Inertia.js 3.11, released at the start of November 2026, adds live props: a page prop that refreshes by itself when a broadcast event fires, with no polling and no hand-written Echo listener. Laravel News covered the release, then published a step-by-step tutorial with Laravel Reverb on November 9. I build most of my Laravel front ends with Inertia and Vue, and real-time updates have always meant extra plumbing. Here is how Inertia live props work, the code to set them up with Reverb, and the caveats I'd check before using them in production.
What live props are
Until now, keeping an Inertia page in sync meant one of two things: polling with router.reload() on a timer, or listening to a channel with Laravel Echo and updating local state yourself. Live props replace both. On the server you wrap a prop in Inertia::live() and name the event that should refresh it. On the client, Inertia subscribes to the event's channel when the page loads, and when the event arrives it does a partial reload of that prop only.
You need Inertia.js 3.11 or later on the client and inertiajs/inertia-laravel 3.7 or later on the server.
Server side: Inertia::live() and a broadcast event
Start with broadcasting. On a fresh app, one command installs Reverb and Echo:
composer require inertiajs/inertia-laravel:^3.7
php artisan install:broadcasting --reverb
Then create an event that implements ShouldBroadcast and returns a channel from broadcastOn(), for example a private channel per order, and authorise it in routes/channels.php so only the order's owner can listen. In the controller, the prop becomes live:
use App\Events\OrderUpdated;
use Inertia\Inertia;
return Inertia::render('Orders/Show', [
'order' => Inertia::live(fn () => $order->fresh(), on: new OrderUpdated($order)),
]);
Creating the event here doesn't broadcast anything: Inertia only reads its channel and name. The closure runs on the first render and again on each reload. Two variations are worth knowing:
// Several events
Inertia::live($value, on: [new OrderUpdated($order), new OrderCancelled($order)]);
// A deferred prop that is also live
'activity' => Inertia::defer(fn () => $order->activity)->live(on: new ActivityLogged($order)),
Public, private, presence and encrypted private channels all work. Merge props can't be live.
Client side: one option in createInertiaApp()
On the Vue side, you pass a transport to createInertiaApp(). With Reverb, that's the echo() helper:
import { createInertiaApp } from '@inertiajs/vue3'
import { echo } from '@inertiajs/vue3/echo'
import { configureEcho } from '@laravel/echo-vue'
configureEcho({ broadcaster: 'reverb' })
createInertiaApp({
live: echo(),
})
That's all: the page component doesn't change. If you want to show that a refresh is in progress, the new useProp() hook gives you a loading flag:
<script setup>
import { useProp } from '@inertiajs/vue3'
const { value, loading } = useProp('order')
</script>
<template>
<span v-if="loading">Refreshing...</span>
</template>
There are also pusher() and actionCable() transports, and you can write your own.
Broadcast the change and run the services
After updating the order, dispatch the event as usual. Every open page showing that order reloads its order prop. To skip the tab that made the change, use broadcast(new OrderUpdated($order))->toOthers(): Inertia now sends the socket ID in an X-Socket-Id header, which is what makes toOthers() work.
Locally you need two processes besides the web server:
php artisan reverb:start
php artisan queue:work # ShouldBroadcast events are queued
Forget the queue worker and nothing happens, with no error: it's the first thing to check. ShouldBroadcastNow skips the queue if you prefer.
Throttling, payloads and the caveats
- Reloads are throttled to one per prop per second by default. For a prop that changes often, raise it:
Inertia::live($value, on: new ActivityLogged, throttle: 4000)(milliseconds). - Hidden tabs pause. Reloads wait until the tab is visible again, which saves requests on dashboards left open all day.
- Each event still costs one request per viewer, unless you send the value in the event itself with
Inertia::broadcastProps()inbroadcastWith(). Be careful: that payload goes to everyone on the channel, so only use it for values that are identical for all viewers, never for per-user data. - Authorise your private channels. A live prop on a public channel tells anyone who subscribes that something changed.
- You are adding infrastructure. Reverb is one more process to run, monitor and restart on deploy, plus a queue worker if you didn't already have one.
Conclusion
Inertia live props turn real-time updates into a one-line change per prop, and the design is sound: the server stays the source of truth, and the client just reloads what changed. I'd start with one screen where stale data hurts, such as an order status or an import progress page, keep the default throttle, and watch the request volume before going further. If you already run Reverb, there is very little reason not to try it.