Optimizing Inertia.js Performance with Partial Reloads
Stop sending massive JSON payloads on every request. Learn how to use Inertia.js partial reloads to refresh specific props, reduce server load, and maintain UI state.
24 Feb 2026, 23:39 UTC

The Problem: The "All or Nothing" Prop Payload
In a standard Inertia.js application, every single request—whether it is a page navigation or a simple data refresh—returns the entire set of props defined for that page. If your dashboard loads a user profile, a list of 50 recent orders, and a heavy set of analytics statistics, every single interaction that triggers a reload sends all three pieces of data back over the wire.
This creates a performance bottleneck. As your page grows, the payload size increases, and the server spends more time querying database relationships that the user doesn't actually need to see update. The goal is to refresh specific slices of the page state without triggering a full page visit or losing the current UI state, such as scroll position or open dropdowns.
How Partial Reloads Work
Partial reloads allow the client to tell the server: "I already have the page layout; just give me the data for these specific keys." This is achieved using the only or except options during a visit or reload. When a partial reload is triggered, Inertia sends an X-Inertia-Partial-Data header to the server.
On the server side, the framework (Laravel, Rails, etc.) detects this header. Instead of executing every query in the controller, you can conditionally load data only when it is requested. This reduces database load and shrinks the JSON response size.
The Client-Side Merge
When the server responds with a partial payload, Inertia performs a shallow merge. If you requested only: ['posts'], the response will contain only the posts key. Inertia replaces the existing posts prop in the page object with the new data. Because the component instance is preserved, Vue, React, or Svelte simply reacts to the prop change, keeping the rest of the UI untouched.
Implementation: Infinite Scroll Example
A common use case for partial reloads is infinite scrolling. Rather than fetching all posts at once, you can fetch the first page and then append subsequent pages without refreshing the entire page state.
// Client-side (Vue 3 example)
import { router, usePage } from '@inertiajs/vue3';
const page = usePage();
const loadMore = () => {
router.reload({
data: { page: page.props.posts.current_page + 1 },
only: ['posts'],
preserveScroll: true,
onSuccess: (page) => {
// Logic to append new posts to the existing list
},
});
};
// Server-side (Laravel Controller)
public function index(Request $request)
{
return Inertia::render('Posts/Index', [
'posts' => Post::query()
->paginate(15),
'heavyStats' => function () {
// This closure is only executed if 'heavyStats'
// is included in the 'only' array or if it's a full visit
return Statistics::calculateExpensiveMetrics();
},
]);
}
Execution Details
- Run Location: The
router.reloadcall runs in the browser; theInertia::renderlogic runs on the server. - Permissions: Standard application user permissions for the requested resource.
- Expected Check: Open the Browser Network tab. The request should show
X-Inertia-Partial-Data: postsand the response JSON should omit theheavyStatskey. - Risk: If you use a closure (Lazy Prop) on the server but forget to include that key in the
onlyarray on the client, the prop will benullor missing in the frontend.
Trade-offs and Limitations
The Shallow Merge Trap
Because Inertia uses a shallow merge, nested objects are replaced entirely. If your prop is user: { profile: { name: 'John' }, settings: { theme: 'dark' } } and you reload only: ['user'], the server must return the entire user object. You cannot partially reload just user.profile. If the server only returns the profile, the settings will be wiped from the client state.
Stale Shared Data
Global shared props (defined in middleware, like auth.user) are not re-evaluated during partial reloads unless they are explicitly listed in the only array. If a user's permissions change or their notification count updates, a partial reload of a page component will not reflect those changes in the global navigation bar.
Verification Checklist
To ensure your partial reloads are working efficiently, verify the following:
- Network Payload: Confirm the response body contains only the requested keys.
- UI Stability: Ensure
preserveScroll: trueis used so the user doesn't jump to the top of the page during a data refresh. - Component State: Verify that local component state (e.g., a text input value) remains intact after the reload.
- Error Handling: Trigger a 422 validation error during a partial reload; confirm that
page.props.errorsis updated without a full page redirect.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.