diff --git a/e2e/react-router/basic-file-based-code-splitting/src/routeTree.gen.ts b/e2e/react-router/basic-file-based-code-splitting/src/routeTree.gen.ts
index 937b3cd783..442312342a 100644
--- a/e2e/react-router/basic-file-based-code-splitting/src/routeTree.gen.ts
+++ b/e2e/react-router/basic-file-based-code-splitting/src/routeTree.gen.ts
@@ -171,7 +171,7 @@ declare module '@tanstack/react-router' {
     '/_layout': {
       id: '/_layout'
       path: ''
-      fullPath: '/'
+      fullPath: ''
       preLoaderRoute: typeof LayoutRouteImport
       parentRoute: typeof rootRouteImport
     }
@@ -199,7 +199,7 @@ declare module '@tanstack/react-router' {
     '/_layout/_layout-2': {
       id: '/_layout/_layout-2'
       path: ''
-      fullPath: '/'
+      fullPath: ''
       preLoaderRoute: typeof LayoutLayout2RouteImport
       parentRoute: typeof LayoutRoute
     }
diff --git a/e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts b/e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts
index 62ce94f2c8..170a6beadb 100644
--- a/e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts
+++ b/e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts
@@ -124,7 +124,7 @@ declare module '@tanstack/react-router' {
     '/_layout': {
       id: '/_layout'
       path: ''
-      fullPath: '/'
+      fullPath: ''
       preLoaderRoute: typeof LayoutRouteImport
       parentRoute: typeof rootRouteImport
     }
@@ -152,7 +152,7 @@ declare module '@tanstack/react-router' {
     '/_layout/_layout-2': {
       id: '/_layout/_layout-2'
       path: ''
-      fullPath: '/'
+      fullPath: ''
       preLoaderRoute: typeof LayoutLayout2RouteImport
       parentRoute: typeof LayoutRoute
     }
diff --git a/e2e/vue-start/custom-basepath/src/routeTree.gen.ts b/e2e/vue-start/custom-basepath/src/routeTree.gen.ts
index ea7e127d8e..2aa189fd3c 100644
--- a/e2e/vue-start/custom-basepath/src/routeTree.gen.ts
+++ b/e2e/vue-start/custom-basepath/src/routeTree.gen.ts
@@ -106,7 +106,7 @@ export interface FileRoutesByFullPath {
   '/redirect/throw-it': typeof RedirectThrowItRoute
   '/users/$userId': typeof UsersUserIdRoute
   '/posts/': typeof PostsIndexRoute
-  '/redirect/': typeof RedirectIndexRoute
+  '/redirect': typeof RedirectIndexRoute
   '/users/': typeof UsersIndexRoute
   '/api/users/$userId': typeof ApiUsersUserIdRoute
   '/posts/$postId/deep': typeof PostsPostIdDeepRoute
@@ -155,7 +155,7 @@ export interface FileRouteTypes {
     | '/redirect/throw-it'
     | '/users/$userId'
     | '/posts/'
-    | '/redirect/'
+    | '/redirect'
     | '/users/'
     | '/api/users/$userId'
     | '/posts/$postId/deep'
@@ -250,7 +250,7 @@ declare module '@tanstack/vue-router' {
     '/redirect/': {
       id: '/redirect/'
       path: '/redirect'
-      fullPath: '/redirect/'
+      fullPath: '/redirect'
       preLoaderRoute: typeof RedirectIndexRouteImport
       parentRoute: typeof rootRouteImport
     }
diff --git a/packages/history/src/index.ts b/packages/history/src/index.ts
index b8151bdf0e..8d70c60da5 100644
--- a/packages/history/src/index.ts
+++ b/packages/history/src/index.ts
@@ -4,13 +4,8 @@
 
 export interface NavigateOptions {
   ignoreBlocker?: boolean
-  /** When true, Transitioner should skip calling load() - commitLocation handles it */
-  skipTransitionerLoad?: boolean
 }
 
-/** Result of a navigation attempt (push/replace) */
-export type NavigationResult = { type: 'SUCCESS' } | { type: 'BLOCKED' }
-
 type SubscriberHistoryAction =
   | {
       type: Exclude<HistoryAction, 'GO'>
@@ -20,10 +15,9 @@ type SubscriberHistoryAction =
       index: number
     }
 
-export type SubscriberArgs = {
+type SubscriberArgs = {
   location: HistoryLocation
   action: SubscriberHistoryAction
-  navigateOpts?: NavigateOptions
 }
 
 export interface RouterHistory {
@@ -31,16 +25,8 @@ export interface RouterHistory {
   length: number
   subscribers: Set<(opts: SubscriberArgs) => void>
   subscribe: (cb: (opts: SubscriberArgs) => void) => () => void
-  push: (
-    path: string,
-    state?: any,
-    navigateOpts?: NavigateOptions,
-  ) => Promise<NavigationResult>
-  replace: (
-    path: string,
-    state?: any,
-    navigateOpts?: NavigateOptions,
-  ) => Promise<NavigationResult>
+  push: (path: string, state?: any, navigateOpts?: NavigateOptions) => void
+  replace: (path: string, state?: any, navigateOpts?: NavigateOptions) => void
   go: (index: number, navigateOpts?: NavigateOptions) => void
   back: (navigateOpts?: NavigateOptions) => void
   forward: (navigateOpts?: NavigateOptions) => void
@@ -70,21 +56,6 @@ export type ParsedHistoryState = HistoryState & {
   key?: string // TODO: Remove in v2 - use __TSR_key instead
   __TSR_key?: string
   __TSR_index: number
-  /** Whether to reset scroll position on this navigation (default: true) */
-  __TSR_resetScroll?: boolean
-  /** Session id for cached TSR internals */
-  __TSR_sessionId?: string
-  /** Match snapshot for fast-path on back/forward navigation */
-  __TSR_matches?: {
-    routeIds: Array<string>
-    params: Record<string, string>
-    globalNotFoundRouteId?: string
-    searchStr?: string
-    validatedSearches?: Array<{
-      search: Record<string, unknown>
-      strictSearch: Record<string, unknown>
-    }>
-  }
 }
 
 type ShouldAllowNavigation = any
@@ -145,14 +116,9 @@ export function createHistory(opts: {
   let location = opts.getLocation()
   const subscribers = new Set<(opts: SubscriberArgs) => void>()
 
-  const notify = (
-    action: SubscriberHistoryAction,
-    navigateOpts?: NavigateOptions,
-  ) => {
+  const notify = (action: SubscriberHistoryAction) => {
     location = opts.getLocation()
-    subscribers.forEach((subscriber) =>
-      subscriber({ location, action, navigateOpts }),
-    )
+    subscribers.forEach((subscriber) => subscriber({ location, action }))
   }
 
   const handleIndexChange = (action: SubscriberHistoryAction) => {
@@ -164,11 +130,11 @@ export function createHistory(opts: {
     task,
     navigateOpts,
     ...actionInfo
-  }: TryNavigateArgs): Promise<NavigationResult> => {
+  }: TryNavigateArgs) => {
     const ignoreBlocker = navigateOpts?.ignoreBlocker ?? false
     if (ignoreBlocker) {
       task()
-      return { type: 'SUCCESS' }
+      return
     }
 
     const blockers = opts.getBlockers?.() ?? []
@@ -184,13 +150,12 @@ export function createHistory(opts: {
         })
         if (isBlocked) {
           opts.onBlocked?.()
-          return { type: 'BLOCKED' }
+          return
         }
       }
     }
 
     task()
-    return { type: 'SUCCESS' }
   }
 
   return {
@@ -211,10 +176,10 @@ export function createHistory(opts: {
     push: (path, state, navigateOpts) => {
       const currentIndex = location.state[stateIndexKey]
       state = assignKeyAndIndex(currentIndex + 1, state)
-      return tryNavigation({
+      tryNavigation({
         task: () => {
           opts.pushState(path, state)
-          notify({ type: 'PUSH' }, navigateOpts)
+          notify({ type: 'PUSH' })
         },
         navigateOpts,
         type: 'PUSH',
@@ -225,10 +190,10 @@ export function createHistory(opts: {
     replace: (path, state, navigateOpts) => {
       const currentIndex = location.state[stateIndexKey]
       state = assignKeyAndIndex(currentIndex, state)
-      return tryNavigation({
+      tryNavigation({
         task: () => {
           opts.replaceState(path, state)
-          notify({ type: 'REPLACE' }, navigateOpts)
+          notify({ type: 'REPLACE' })
         },
         navigateOpts,
         type: 'REPLACE',
diff --git a/packages/react-router/src/Transitioner.tsx b/packages/react-router/src/Transitioner.tsx
index de38e5b8d4..83fb46cfe0 100644
--- a/packages/react-router/src/Transitioner.tsx
+++ b/packages/react-router/src/Transitioner.tsx
@@ -7,7 +7,6 @@ import {
 import { useLayoutEffect, usePrevious } from './utils'
 import { useRouter } from './useRouter'
 import { useRouterState } from './useRouterState'
-import type { SubscriberArgs } from '@tanstack/history'
 
 export function Transitioner() {
   const router = useRouter()
@@ -42,17 +41,7 @@ export function Transitioner() {
   // Subscribe to location changes
   // and try to load the new location
   React.useEffect(() => {
-    const unsub = router.history.subscribe(
-      ({ navigateOpts }: SubscriberArgs) => {
-        // If commitLocation initiated this navigation, it handles load() itself
-        if (navigateOpts?.skipTransitionerLoad) {
-          return
-        }
-
-        // External navigation (pop, direct history.push, etc): call load normally
-        router.load()
-      },
-    )
+    const unsub = router.history.subscribe(router.load)
 
     const nextLocation = router.buildLocation({
       to: router.latestLocation.pathname,
diff --git a/packages/react-router/tests/Matches.test.tsx b/packages/react-router/tests/Matches.test.tsx
index 03cf65530e..dd3ca3dfa6 100644
--- a/packages/react-router/tests/Matches.test.tsx
+++ b/packages/react-router/tests/Matches.test.tsx
@@ -344,7 +344,7 @@ describe('matching on different param types', () => {
 
       await act(() => render(<RouterProvider router={router} />))
 
-      await act(() => router.history.push(nav))
+      act(() => router.history.push(nav))
 
       const paramsToCheck = await screen.findByTestId('params')
       const matchesToCheck = await screen.findByTestId('matches')
diff --git a/packages/react-router/tests/useNavigate.test.tsx b/packages/react-router/tests/useNavigate.test.tsx
index eca4f92a5c..44db285f47 100644
--- a/packages/react-router/tests/useNavigate.test.tsx
+++ b/packages/react-router/tests/useNavigate.test.tsx
@@ -7,7 +7,6 @@ import {
   fireEvent,
   render,
   screen,
-  waitFor,
 } from '@testing-library/react'
 
 import { z } from 'zod'
@@ -1317,11 +1316,9 @@ test('when setting search params with 2 parallel navigate calls', async () => {
   })
 
   render(<RouterProvider router={router} />)
-  await waitFor(() => {
-    expect(router.state.location.search).toEqual({
-      param1: 'param1-default',
-      param2: 'param2-default',
-    })
+  expect(router.state.location.search).toEqual({
+    param1: 'param1-default',
+    param2: 'param2-default',
   })
 
   const postsButton = await screen.findByRole('button', { name: 'search' })
@@ -1330,12 +1327,7 @@ test('when setting search params with 2 parallel navigate calls', async () => {
 
   expect(await screen.findByTestId('param1')).toHaveTextContent('foo')
   expect(await screen.findByTestId('param2')).toHaveTextContent('bar')
-  await waitFor(() => {
-    expect(router.state.location.search).toEqual({
-      param1: 'foo',
-      param2: 'bar',
-    })
-  })
+  expect(router.state.location.search).toEqual({ param1: 'foo', param2: 'bar' })
   const search = new URLSearchParams(window.location.search)
   expect(search.get('param1')).toEqual('foo')
   expect(search.get('param2')).toEqual('bar')
@@ -1455,27 +1447,21 @@ test.each([true, false])(
 
     fireEvent.click(postButton)
 
-    await waitFor(() => {
-      expect(router.state.location.pathname).toBe(`/post${tail}`)
-    })
+    expect(router.state.location.pathname).toBe(`/post${tail}`)
 
     const searchButton = await screen.findByTestId('search-btn')
 
     fireEvent.click(searchButton)
 
-    await waitFor(() => {
-      expect(router.state.location.pathname).toBe(`/post${tail}`)
-      expect(router.state.location.search).toEqual({ param1: 'value1' })
-    })
+    expect(router.state.location.pathname).toBe(`/post${tail}`)
+    expect(router.state.location.search).toEqual({ param1: 'value1' })
 
     const searchButton2 = await screen.findByTestId('search2-btn')
 
     fireEvent.click(searchButton2)
 
-    await waitFor(() => {
-      expect(router.state.location.pathname).toBe(`/post${tail}`)
-      expect(router.state.location.search).toEqual({ param1: 'value2' })
-    })
+    expect(router.state.location.pathname).toBe(`/post${tail}`)
+    expect(router.state.location.search).toEqual({ param1: 'value2' })
   },
 )
 
@@ -1774,28 +1760,22 @@ test.each([true, false])(
 
     fireEvent.click(detail1AddBtn)
 
-    await waitFor(() => {
-      expect(router.state.location.pathname).toBe(`/posts/id1/detail${tail}`)
-      expect(router.state.location.search).toEqual({ _test: true })
-    })
+    expect(router.state.location.pathname).toBe(`/posts/id1/detail${tail}`)
+    expect(router.state.location.search).toEqual({ _test: true })
 
     const detail1RemoveBtn = await screen.findByTestId('detail-btn-remove-1')
 
     fireEvent.click(detail1RemoveBtn)
 
-    await waitFor(() => {
-      expect(router.state.location.pathname).toBe(`/posts/id1/detail${tail}`)
-      expect(router.state.location.search).toEqual({})
-    })
+    expect(router.state.location.pathname).toBe(`/posts/id1/detail${tail}`)
+    expect(router.state.location.search).toEqual({})
 
     const detail2AddBtn = await screen.findByTestId('detail-btn-add-2')
 
     fireEvent.click(detail2AddBtn)
 
-    await waitFor(() => {
-      expect(router.state.location.pathname).toBe(`/posts/id1/detail${tail}`)
-      expect(router.state.location.search).toEqual({ _test: true })
-    })
+    expect(router.state.location.pathname).toBe(`/posts/id1/detail${tail}`)
+    expect(router.state.location.search).toEqual({ _test: true })
   },
 )
 
diff --git a/packages/router-core/src/index.ts b/packages/router-core/src/index.ts
index deff8f6f8e..1897f07880 100644
--- a/packages/router-core/src/index.ts
+++ b/packages/router-core/src/index.ts
@@ -69,11 +69,7 @@ export type {
   CreateLazyFileRoute,
 } from './fileRoute'
 
-export type {
-  MatchSnapshot,
-  ParsedLocation,
-  ValidatedSearchEntry,
-} from './location'
+export type { ParsedLocation } from './location'
 export type { Manifest, RouterManagedTag } from './manifest'
 export { isMatch } from './Matches'
 export type {
diff --git a/packages/router-core/src/location.ts b/packages/router-core/src/location.ts
index ed854c4d74..2e2c8042cf 100644
--- a/packages/router-core/src/location.ts
+++ b/packages/router-core/src/location.ts
@@ -1,35 +1,6 @@
 import type { ParsedHistoryState } from '@tanstack/history'
 import type { AnySchema } from './validators'
 
-/**
- * Per-route validated search result cached in snapshot.
- */
-export interface ValidatedSearchEntry {
-  /** Merged search (parent + this route's validated) */
-  search: Record<string, unknown>
-  /** Strict search (only this route's validated fields) */
-  strictSearch: Record<string, unknown>
-}
-
-/**
- * Match snapshot stored in history state for fast-path on back/forward navigation.
- * Allows skipping path matching by storing route IDs and params.
- */
-export interface MatchSnapshot {
-  /** Ordered route IDs that matched */
-  routeIds: Array<string>
-  /** Raw path params extracted from the URL */
-  params: Record<string, string>
-  /** Parsed/validated path params */
-  parsedParams: Record<string, unknown>
-  /** Route ID that should show global not found, if any */
-  globalNotFoundRouteId?: string
-  /** Search string when snapshot was created (for cache invalidation) */
-  searchStr?: string
-  /** Per-route validated search results (parallel to routeIds) */
-  validatedSearches?: Array<ValidatedSearchEntry>
-}
-
 export interface ParsedLocation<TSearchObj extends AnySchema = {}> {
   /**
    * The full path of the location, including pathname, search, and hash.
@@ -77,10 +48,4 @@ export interface ParsedLocation<TSearchObj extends AnySchema = {}> {
    * @private
    */
   url: URL
-  /**
-   * @internal
-   * @description Match snapshot for fast-path on back/forward navigation.
-   * Contains route IDs and params from buildLocation to avoid re-matching.
-   */
-  _matchSnapshot?: MatchSnapshot
 }
diff --git a/packages/router-core/src/router.ts b/packages/router-core/src/router.ts
index 05e6c49fd8..4946c8aefb 100644
--- a/packages/router-core/src/router.ts
+++ b/packages/router-core/src/router.ts
@@ -56,7 +56,7 @@ import type {
   PickAsRequired,
   Updater,
 } from './utils'
-import type { MatchSnapshot, ParsedLocation } from './location'
+import type { ParsedLocation } from './location'
 import type {
   AnyContext,
   AnyRoute,
@@ -590,14 +590,6 @@ export interface MatchRoutesOpts {
   throwOnError?: boolean
   _buildLocation?: boolean
   dest?: BuildNextOptions
-  /** Optional match snapshot hint for fast-path (skips path matching) */
-  snapshot?: MatchSnapshot
-}
-
-export interface MatchRoutesResult {
-  matches: Array<AnyRouteMatch>
-  /** Raw string params extracted from path (before parsing) */
-  rawParams: Record<string, string>
 }
 
 export type InferRouterContext<TRouteTree extends AnyRoute> =
@@ -710,17 +702,14 @@ export type GetMatchRoutesFn = (pathname: string) => {
   /** exhaustive params, still in their string form */
   routeParams: Record<string, string>
   /** partial params, parsed from routeParams during matching */
-  parsedParams: Record<string, unknown>
+  parsedParams: Record<string, unknown> | undefined
   foundRoute: AnyRoute | undefined
   parseError?: unknown
 }
 
 export type EmitFn = (routerEvent: RouterEvent) => void
 
-export type LoadFn = (opts?: {
-  sync?: boolean
-  _skipUpdateLatestLocation?: boolean
-}) => Promise<void>
+export type LoadFn = (opts?: { sync?: boolean }) => Promise<void>
 
 export type CommitLocationFn = ({
   viewTransition,
@@ -903,6 +892,7 @@ export class RouterCore<
   tempLocationKey: string | undefined = `${Math.round(
     Math.random() * 10000000,
   )}`
+  resetNextScroll = true
   shouldViewTransition?: boolean | ViewTransitionOptions = undefined
   isViewTransitionTypesSupported?: boolean = undefined
   subscribers = new Set<RouterListener<RouterEvent>>()
@@ -927,8 +917,6 @@ export class RouterCore<
   origin?: string
   latestLocation!: ParsedLocation<FullSearchSchema<TRouteTree>>
   pendingBuiltLocation?: ParsedLocation<FullSearchSchema<TRouteTree>>
-  /** Session id for cached history snapshots */
-  private sessionId!: string
   basepath!: string
   routeTree!: TRouteTree
   routesById!: RoutesById<TRouteTree>
@@ -949,11 +937,6 @@ export class RouterCore<
       TDehydrated
     >,
   ) {
-    this.sessionId =
-      typeof crypto !== 'undefined' && 'randomUUID' in crypto
-        ? crypto.randomUUID()
-        : `${Date.now()}-${Math.random().toString(36).slice(2)}`
-
     this.update({
       defaultPreloadDelay: 50,
       defaultPendingMs: 1000,
@@ -1271,70 +1254,42 @@ export class RouterCore<
           search: locationSearchOrOpts,
         } as ParsedLocation,
         opts,
-      ).matches
+      )
     }
 
     return this.matchRoutesInternal(pathnameOrNext, locationSearchOrOpts)
-      .matches
   }
 
   private matchRoutesInternal(
     next: ParsedLocation,
     opts?: MatchRoutesOpts,
-  ): MatchRoutesResult {
-    // Fast-path: use snapshot hint if valid
-    const snapshot = opts?.snapshot
-    const snapshotValid =
-      snapshot &&
-      snapshot.routeIds.length > 0 &&
-      snapshot.routeIds.every((id) => this.routesById[id])
-
-    let matchedRoutes: ReadonlyArray<AnyRoute>
-    let routeParams: Record<string, string>
-    let rawParams: Record<string, string>
-    let globalNotFoundRouteId: string | undefined
-    let parsedParams: Record<string, unknown>
-
-    if (snapshotValid) {
-      // Rebuild matched routes from snapshot
-      matchedRoutes = snapshot.routeIds.map((id) => this.routesById[id]!)
-      routeParams = { ...snapshot.params }
-      rawParams = { ...snapshot.params }
-      globalNotFoundRouteId = snapshot.globalNotFoundRouteId
-      parsedParams = snapshot.parsedParams
-    } else {
-      // Normal path matching
-      const matchedRoutesResult = this.getMatchedRoutes(next.pathname)
-      const { foundRoute, routeParams: rp } = matchedRoutesResult
-      routeParams = rp
-      rawParams = { ...rp } // Capture before routeParams gets modified
-      matchedRoutes = matchedRoutesResult.matchedRoutes
-      parsedParams = matchedRoutesResult.parsedParams
+  ): Array<AnyRouteMatch> {
+    const matchedRoutesResult = this.getMatchedRoutes(next.pathname)
+    const { foundRoute, routeParams, parsedParams } = matchedRoutesResult
+    let { matchedRoutes } = matchedRoutesResult
+    let isGlobalNotFound = false
 
-      let isGlobalNotFound = false
-
-      // Check to see if the route needs a 404 entry
-      if (
-        // If we found a route, and it's not an index route and we have left over path
-        foundRoute
-          ? foundRoute.path !== '/' && routeParams['**']
-          : // Or if we didn't find a route and we have left over path
-            trimPathRight(next.pathname)
-      ) {
-        // If the user has defined an (old) 404 route, use it
-        if (this.options.notFoundRoute) {
-          matchedRoutes = [...matchedRoutes, this.options.notFoundRoute]
-        } else {
-          // If there is no routes found during path matching
-          isGlobalNotFound = true
-        }
+    // Check to see if the route needs a 404 entry
+    if (
+      // If we found a route, and it's not an index route and we have left over path
+      foundRoute
+        ? foundRoute.path !== '/' && routeParams['**']
+        : // Or if we didn't find a route and we have left over path
+          trimPathRight(next.pathname)
+    ) {
+      // If the user has defined an (old) 404 route, use it
+      if (this.options.notFoundRoute) {
+        matchedRoutes = [...matchedRoutes, this.options.notFoundRoute]
+      } else {
+        // If there is no routes found during path matching
+        isGlobalNotFound = true
       }
-
-      globalNotFoundRouteId = isGlobalNotFound
-        ? findGlobalNotFoundRouteId(this.options.notFoundMode, matchedRoutes)
-        : undefined
     }
 
+    const globalNotFoundRouteId = isGlobalNotFound
+      ? findGlobalNotFoundRouteId(this.options.notFoundMode, matchedRoutes)
+      : undefined
+
     const matches: Array<AnyRouteMatch> = []
 
     const getParentContext = (parentMatch?: AnyRouteMatch) => {
@@ -1347,19 +1302,6 @@ export class RouterCore<
       return parentContext
     }
 
-    // Check if we can use cached validated searches from snapshot
-    // Valid if: snapshot exists, searchStr matches, and validatedSearches has correct length
-    const canUseCachedSearch =
-      snapshotValid &&
-      snapshot.searchStr === next.searchStr &&
-      snapshot.validatedSearches?.length === matchedRoutes.length
-
-    // Collect validated searches to cache in snapshot (only when not using cache)
-    const validatedSearchesToCache: Array<{
-      search: Record<string, unknown>
-      strictSearch: Record<string, unknown>
-    }> = []
-
     matchedRoutes.forEach((route, index) => {
       // Take each matched route and resolve + validate its search params
       // This has to happen serially because each route's search params
@@ -1375,12 +1317,6 @@ export class RouterCore<
         Record<string, any>,
         any,
       ] = (() => {
-        // Fast-path: use cached validated search from snapshot
-        if (canUseCachedSearch) {
-          const cached = snapshot.validatedSearches![index]!
-          return [cached.search, cached.strictSearch, undefined]
-        }
-
         // Validate the search params and stabilize them
         const parentSearch = parentMatch?.search ?? next.search
         const parentStrictSearch = parentMatch?._strictSearch ?? undefined
@@ -1414,14 +1350,6 @@ export class RouterCore<
         }
       })()
 
-      // Cache the validated search for future pop navigations
-      if (!canUseCachedSearch) {
-        validatedSearchesToCache.push({
-          search: preMatchSearch,
-          strictSearch: strictMatchSearch,
-        })
-      }
-
       // This is where we need to call route.options.loaderDeps() to get any additional
       // deps that the route's loader function might need to run. We need to do this
       // before we create the match so that we can pass the deps to the route's
@@ -1588,18 +1516,6 @@ export class RouterCore<
       matches.push(match)
     })
 
-    // Cache validated searches in snapshot for future pop navigations
-    // Only update if we computed fresh values (not using cached)
-    if (!canUseCachedSearch && validatedSearchesToCache.length > 0) {
-      const existingSnapshot = next.state?.__TSR_matches as
-        | MatchSnapshot
-        | undefined
-      if (existingSnapshot) {
-        existingSnapshot.searchStr = next.searchStr
-        existingSnapshot.validatedSearches = validatedSearchesToCache
-      }
-    }
-
     matches.forEach((match, index) => {
       const route = this.looseRoutesById[match.routeId]!
       const existingMatch = this.getMatch(match.id)
@@ -1639,7 +1555,7 @@ export class RouterCore<
       }
     })
 
-    return { matches, rawParams }
+    return matches
   }
 
   getMatchedRoutes: GetMatchRoutesFn = (pathname) => {
@@ -1767,7 +1683,6 @@ export class RouterCore<
       // which are expensive and not needed for buildLocation
       const destMatchResult = this.getMatchedRoutes(interpolatedNextTo)
       let destRoutes = destMatchResult.matchedRoutes
-      const rawParams = destMatchResult.routeParams
 
       // Compute globalNotFoundRouteId using the same logic as matchRoutesInternal
       const isGlobalNotFound = destMatchResult.foundRoute
@@ -1867,20 +1782,6 @@ export class RouterCore<
       // Replace the equal deep
       nextState = replaceEqualDeep(currentLocation.state, nextState)
 
-      // Build match snapshot for fast-path on back/forward navigation
-      // Use raw params captured during matchRoutesInternal (needed for literal path navigation
-      // where nextParams may be empty but path contains param values)
-      const snapshotParams = {
-        ...rawParams,
-        ...nextParams,
-      }
-      const matchSnapshot = buildMatchSnapshotFromRoutes({
-        routes: destRoutes,
-        params: snapshotParams,
-        searchStr,
-        globalNotFoundRouteId,
-      })
-
       // Create the full path of the location
       const fullPath = `${nextPathname}${searchStr}${hashStr}`
 
@@ -1890,13 +1791,10 @@ export class RouterCore<
       // If a rewrite function is provided, use it to rewrite the URL
       const rewrittenUrl = executeRewriteOutput(this.rewrite, url)
 
-      // Use encoded URL path for href (consistent with parseLocation)
-      const encodedHref = url.href.replace(url.origin, '')
-
       return {
         publicHref:
           rewrittenUrl.pathname + rewrittenUrl.search + rewrittenUrl.hash,
-        href: encodedHref,
+        href: fullPath,
         url: rewrittenUrl,
         pathname: nextPathname,
         search: nextSearch,
@@ -1904,7 +1802,6 @@ export class RouterCore<
         state: nextState as any,
         hash: hash ?? '',
         unmaskOnReload: dest.unmaskOnReload,
-        _matchSnapshot: matchSnapshot,
       }
     }
 
@@ -2010,105 +1907,65 @@ export class RouterCore<
     // Don't commit to history if nothing changed
     if (isSameUrl && isSameState()) {
       this.load()
-      return this.commitLocationPromise
-    }
-
-    let {
-      // eslint-disable-next-line prefer-const
-      maskedLocation,
-      // eslint-disable-next-line prefer-const
-      hashScrollIntoView,
-      // don't pass url into history since it is a URL instance that cannot be serialized
-      // eslint-disable-next-line prefer-const
-      url: _url,
-      ...nextHistory
-    } = next
-
-    if (maskedLocation) {
-      nextHistory = {
-        ...maskedLocation,
-        state: {
-          ...maskedLocation.state,
-          __tempKey: undefined,
-          __tempLocation: {
-            ...nextHistory,
-            search: nextHistory.searchStr,
-            state: {
-              ...nextHistory.state,
-              __tempKey: undefined!,
-              __tempLocation: undefined!,
-              __TSR_key: undefined!,
-              key: undefined!, // TODO: Remove in v2 - use __TSR_key instead
+    } else {
+      let {
+        // eslint-disable-next-line prefer-const
+        maskedLocation,
+        // eslint-disable-next-line prefer-const
+        hashScrollIntoView,
+        // don't pass url into history since it is a URL instance that cannot be serialized
+        // eslint-disable-next-line prefer-const
+        url: _url,
+        ...nextHistory
+      } = next
+
+      if (maskedLocation) {
+        nextHistory = {
+          ...maskedLocation,
+          state: {
+            ...maskedLocation.state,
+            __tempKey: undefined,
+            __tempLocation: {
+              ...nextHistory,
+              search: nextHistory.searchStr,
+              state: {
+                ...nextHistory.state,
+                __tempKey: undefined!,
+                __tempLocation: undefined!,
+                __TSR_key: undefined!,
+                key: undefined!, // TODO: Remove in v2 - use __TSR_key instead
+              },
             },
           },
-        },
-      }
+        }
 
-      if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
-        nextHistory.state.__tempKey = this.tempLocationKey
+        if (
+          nextHistory.unmaskOnReload ??
+          this.options.unmaskOnReload ??
+          false
+        ) {
+          nextHistory.state.__tempKey = this.tempLocationKey
+        }
       }
-    }
-
-    nextHistory.state.__hashScrollIntoViewOptions =
-      hashScrollIntoView ?? this.options.defaultHashScrollIntoView ?? true
-
-    // Store resetScroll in history state so it survives back/forward navigation
-    nextHistory.state.__TSR_resetScroll = next.resetScroll ?? true
 
-    this.shouldViewTransition = viewTransition
+      nextHistory.state.__hashScrollIntoViewOptions =
+        hashScrollIntoView ?? this.options.defaultHashScrollIntoView ?? true
 
-    // Store session id for this router lifetime
-    nextHistory.state.__TSR_sessionId = this.sessionId
+      this.shouldViewTransition = viewTransition
 
-    // Use match snapshot from buildLocation if available, otherwise compute it.
-    // Stored in history state for pop/back/forward fast-path.
-    nextHistory.state.__TSR_matches =
-      next._matchSnapshot ??
-      buildMatchSnapshot({
-        matchResult: this.getMatchedRoutes(next.pathname),
-        pathname: next.pathname,
-        searchStr: next.searchStr,
-        notFoundRoute: this.options.notFoundRoute,
-        notFoundMode: this.options.notFoundMode,
-      })
-
-    // Build the pre-computed ParsedLocation to avoid re-parsing after push
-    // Spread next (which has href, pathname, search, etc.) and override with final state
-    const precomputedLocation: ParsedLocation = {
-      ...next,
-      publicHref: nextHistory.publicHref,
-      state: nextHistory.state,
-      maskedLocation,
+      this.history[next.replace ? 'replace' : 'push'](
+        nextHistory.publicHref,
+        nextHistory.state,
+        { ignoreBlocker },
+      )
     }
 
-    // Await push/replace to handle blockers before proceeding
-    // Pass skipTransitionerLoad so Transitioner doesn't call load() - we handle it below
-    const result = await this.history[next.replace ? 'replace' : 'push'](
-      nextHistory.publicHref,
-      nextHistory.state,
-      { ignoreBlocker, skipTransitionerLoad: true },
-    )
-
-    // If blocked, resolve promise and return
-    if (result.type === 'BLOCKED') {
-      this.commitLocationPromise?.resolve()
-      return this.commitLocationPromise
-    }
+    this.resetNextScroll = next.resetScroll ?? true
 
-    // Check if another navigation has superseded this one while we awaited
-    // If so, let the newer navigation handle things - don't overwrite latestLocation
-    if (this.history.location.href !== nextHistory.publicHref) {
-      return this.commitLocationPromise
+    if (!this.history.subscribers.size) {
+      this.load()
     }
 
-    // Success: set latestLocation directly (we skip updateLatestLocation in load)
-    this.latestLocation = precomputedLocation as unknown as ParsedLocation<
-      FullSearchSchema<TRouteTree>
-    >
-
-    // Call load() with _skipUpdateLatestLocation since we already set latestLocation
-    this.load({ _skipUpdateLatestLocation: true })
-
     return this.commitLocationPromise
   }
 
@@ -2260,14 +2117,10 @@ export class RouterCore<
 
   latestLoadPromise: undefined | Promise<void>
 
-  beforeLoad = (opts?: { _skipUpdateLatestLocation?: boolean }) => {
+  beforeLoad = () => {
     // Cancel any pending matches
     this.cancelMatches()
-    if (!opts?._skipUpdateLatestLocation) {
-      this.updateLatestLocation()
-    } else {
-      // Already have latestLocation from commitLocation, skip parsing
-    }
+    this.updateLatestLocation()
 
     if (this.isServer) {
       // for SPAs on the initial load, this is handled by the Transitioner
@@ -2291,12 +2144,7 @@ export class RouterCore<
     }
 
     // Match the routes
-    // Use snapshot from history state for fast-path only within same router lifetime
-    const snapshot =
-      this.latestLocation.state.__TSR_sessionId === this.sessionId
-        ? this.latestLocation.state.__TSR_matches
-        : undefined
-    const pendingMatches = this.matchRoutes(this.latestLocation, { snapshot })
+    const pendingMatches = this.matchRoutes(this.latestLocation)
 
     // Ingest the new matches
     this.__store.setState((s) => ({
@@ -2313,10 +2161,7 @@ export class RouterCore<
     }))
   }
 
-  load: LoadFn = async (opts?: {
-    sync?: boolean
-    _skipUpdateLatestLocation?: boolean
-  }): Promise<void> => {
+  load: LoadFn = async (opts?: { sync?: boolean }): Promise<void> => {
     let redirect: AnyRedirect | undefined
     let notFound: NotFoundError | undefined
     let loadPromise: Promise<void>
@@ -2325,9 +2170,7 @@ export class RouterCore<
     loadPromise = new Promise<void>((resolve) => {
       this.startTransition(async () => {
         try {
-          this.beforeLoad({
-            _skipUpdateLatestLocation: opts?._skipUpdateLatestLocation,
-          })
+          this.beforeLoad()
           const next = this.latestLocation
           const prevLocation = this.state.resolvedLocation
 
@@ -2935,7 +2778,7 @@ export function getMatchedRoutes<TRouteLike extends RouteLike>({
   const trimmedPath = trimPathRight(pathname)
 
   let foundRoute: TRouteLike | undefined = undefined
-  let parsedParams: Record<string, unknown> = {}
+  let parsedParams: Record<string, unknown> | undefined = undefined
   const match = findRouteMatch<TRouteLike>(trimmedPath, processedTree, true)
   if (match) {
     foundRoute = match.route
@@ -2948,96 +2791,6 @@ export function getMatchedRoutes<TRouteLike extends RouteLike>({
   return { matchedRoutes, routeParams, foundRoute, parsedParams }
 }
 
-/**
- * Build a MatchSnapshot from a getMatchedRoutes result.
- * Determines globalNotFoundRouteId using the same logic as matchRoutesInternal.
- */
-export function buildMatchSnapshot({
-  matchResult,
-  pathname,
-  searchStr,
-  notFoundRoute,
-  notFoundMode,
-}: {
-  matchResult: ReturnType<typeof getMatchedRoutes>
-  pathname: string
-  searchStr?: string
-  notFoundRoute?: AnyRoute
-  notFoundMode?: 'root' | 'fuzzy'
-}): MatchSnapshot {
-  const snapshot: MatchSnapshot = {
-    routeIds: matchResult.matchedRoutes.map((r) => r.id),
-    params: matchResult.routeParams,
-    parsedParams: matchResult.parsedParams,
-    searchStr,
-  }
-
-  const isGlobalNotFound = matchResult.foundRoute
-    ? matchResult.foundRoute.path !== '/' && matchResult.routeParams['**']
-    : trimPathRight(pathname)
-
-  if (isGlobalNotFound) {
-    if (notFoundRoute) {
-      // Custom notFoundRoute provided - use its id
-      snapshot.globalNotFoundRouteId = notFoundRoute.id
-    } else {
-      if (notFoundMode !== 'root') {
-        for (let i = matchResult.matchedRoutes.length - 1; i >= 0; i--) {
-          const route = matchResult.matchedRoutes[i]!
-          if (route.children) {
-            snapshot.globalNotFoundRouteId = route.id
-            break
-          }
-        }
-      }
-      if (!snapshot.globalNotFoundRouteId) {
-        snapshot.globalNotFoundRouteId = rootRouteId
-      }
-    }
-  }
-
-  return snapshot
-}
-
-/**
- * Build a MatchSnapshot from routes and params directly.
- * Used by buildLocation to avoid duplicate getMatchedRoutes call.
- */
-export function buildMatchSnapshotFromRoutes({
-  routes,
-  params,
-  searchStr,
-  globalNotFoundRouteId,
-}: {
-  routes: ReadonlyArray<AnyRoute>
-  params: Record<string, unknown>
-  searchStr?: string
-  globalNotFoundRouteId?: string
-}): MatchSnapshot {
-  // Convert all params to strings for snapshot storage
-  // (params from path matching are always strings)
-  const stringParams: Record<string, string> = {}
-  for (const key in params) {
-    const value = params[key]
-    if (value != null) {
-      stringParams[key] = String(value)
-    }
-  }
-
-  const snapshot: MatchSnapshot = {
-    routeIds: routes.map((r) => r.id),
-    params: stringParams,
-    parsedParams: params,
-    searchStr,
-  }
-
-  if (globalNotFoundRouteId) {
-    snapshot.globalNotFoundRouteId = globalNotFoundRouteId
-  }
-
-  return snapshot
-}
-
 /**
  * TODO: once caches are persisted across requests on the server,
  * we can cache the built middleware chain using `last(destRoutes)` as the key
diff --git a/packages/router-core/src/scroll-restoration.ts b/packages/router-core/src/scroll-restoration.ts
index 88eec46775..c8614429a9 100644
--- a/packages/router-core/src/scroll-restoration.ts
+++ b/packages/router-core/src/scroll-restoration.ts
@@ -340,8 +340,8 @@ export function setupScrollRestoration(router: AnyRouter, force?: boolean) {
 
     // If the user doesn't want to restore the scroll position,
     // we don't need to do anything.
-    const resetScroll = event.toLocation.state.__TSR_resetScroll ?? true
-    if (!resetScroll) {
+    if (!router.resetNextScroll) {
+      router.resetNextScroll = true
       return
     }
     if (typeof router.options.scrollRestoration === 'function') {
diff --git a/packages/router-core/tests/load.test.ts b/packages/router-core/tests/load.test.ts
index db5c498c2e..3a3d807800 100644
--- a/packages/router-core/tests/load.test.ts
+++ b/packages/router-core/tests/load.test.ts
@@ -82,8 +82,6 @@ describe('beforeLoad skip or exec', () => {
     const beforeLoad = vi.fn(() => Promise.resolve({ hello: 'world' }))
     const router = setup({ beforeLoad })
     const navigation = router.navigate({ to: '/foo' })
-    // With async history.push, load() runs after a microtask
-    await Promise.resolve()
     expect(beforeLoad).toHaveBeenCalledTimes(1)
     expect(router.state.pendingMatches).toEqual(
       expect.arrayContaining([expect.objectContaining({ id: '/foo/foo' })]),
@@ -266,8 +264,6 @@ describe('loader skip or exec', () => {
     const loader = vi.fn(() => Promise.resolve({ hello: 'world' }))
     const router = setup({ loader })
     const navigation = router.navigate({ to: '/foo' })
-    // With async history.push, load() runs after a microtask
-    await Promise.resolve()
     expect(loader).toHaveBeenCalledTimes(1)
     expect(router.state.pendingMatches).toEqual(
       expect.arrayContaining([expect.objectContaining({ id: '/foo/foo' })]),
diff --git a/packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx b/packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx
index 7e86807113..67e67877d3 100644
--- a/packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx
+++ b/packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx
@@ -354,6 +354,7 @@ export const BaseTanStackRouterDevtoolsPanel =
                 'subscribers',
                 'latestLoadPromise',
                 'navigateTimeout',
+                'resetNextScroll',
                 'tempLocationKey',
                 'latestLocation',
                 'routeTree',
diff --git a/packages/solid-router/src/Transitioner.tsx b/packages/solid-router/src/Transitioner.tsx
index c1100e3dc7..c9df0b2053 100644
--- a/packages/solid-router/src/Transitioner.tsx
+++ b/packages/solid-router/src/Transitioner.tsx
@@ -7,7 +7,6 @@ import {
 import { useRouter } from './useRouter'
 import { useRouterState } from './useRouterState'
 import { usePrevious } from './utils'
-import type { SubscriberArgs } from '@tanstack/history'
 
 export function Transitioner() {
   const router = useRouter()
@@ -45,17 +44,7 @@ export function Transitioner() {
   // Subscribe to location changes
   // and try to load the new location
   Solid.onMount(() => {
-    const unsub = router.history.subscribe(
-      ({ navigateOpts }: SubscriberArgs) => {
-        // If commitLocation initiated this navigation, it handles load() itself
-        if (navigateOpts?.skipTransitionerLoad) {
-          return
-        }
-
-        // External navigation (pop, direct history.push, etc): call load normally
-        router.load()
-      },
-    )
+    const unsub = router.history.subscribe(router.load)
 
     const nextLocation = router.buildLocation({
       to: router.latestLocation.pathname,
diff --git a/packages/solid-router/tests/link.test.tsx b/packages/solid-router/tests/link.test.tsx
index e793dbc2cd..5adfee2247 100644
--- a/packages/solid-router/tests/link.test.tsx
+++ b/packages/solid-router/tests/link.test.tsx
@@ -777,19 +777,13 @@ describe('Link', () => {
 
     await fireEvent.click(updateSearchLink)
 
-    // Wait for navigation to complete and UI to update
+    // Wait for navigation to complete and search params to update
     await waitFor(() => {
       expect(window.location.search).toBe('?page=2&filter=inactive')
     })
 
-    // Wait for the UI to reflect the new search params
-    await waitFor(() => {
-      const page = screen.getByTestId('current-page')
-      expect(page).toHaveTextContent('Page: 2')
-    })
-
-    const updatedPage = screen.getByTestId('current-page')
-    const updatedFilter = screen.getByTestId('current-filter')
+    const updatedPage = await screen.findByTestId('current-page')
+    const updatedFilter = await screen.findByTestId('current-filter')
 
     // Verify search was updated
     expect(window.location.pathname).toBe('/posts')
diff --git a/packages/vue-router/src/Transitioner.tsx b/packages/vue-router/src/Transitioner.tsx
index c9a3728cc6..4b4c231677 100644
--- a/packages/vue-router/src/Transitioner.tsx
+++ b/packages/vue-router/src/Transitioner.tsx
@@ -7,7 +7,6 @@ import {
 import { useRouter } from './useRouter'
 import { useRouterState } from './useRouterState'
 import { usePrevious } from './utils'
-import type { SubscriberArgs } from '@tanstack/history'
 
 // Track mount state per router to avoid double-loading
 let mountLoadForRouter = { router: null as any, mounted: false }
@@ -113,17 +112,7 @@ export function useTransitionerSetup() {
   let unsubscribe: (() => void) | undefined
 
   Vue.onMounted(() => {
-    unsubscribe = router.history.subscribe(
-      ({ navigateOpts }: SubscriberArgs) => {
-        // If commitLocation initiated this navigation, it handles load() itself
-        if (navigateOpts?.skipTransitionerLoad) {
-          return
-        }
-
-        // External navigation (pop, direct history.push, etc): call load normally
-        router.load()
-      },
-    )
+    unsubscribe = router.history.subscribe(router.load)
 
     const nextLocation = router.buildLocation({
       to: router.latestLocation.pathname,
diff --git a/packages/vue-router/tests/link.test.tsx b/packages/vue-router/tests/link.test.tsx
index fa348470ed..b49cc08fb8 100644
--- a/packages/vue-router/tests/link.test.tsx
+++ b/packages/vue-router/tests/link.test.tsx
@@ -3991,13 +3991,10 @@ describe('Link', () => {
     const onPostsText = await screen.findByText('On Posts')
     expect(onPostsText).toBeInTheDocument()
 
-    // Wait for the UI to update after navigation
-    await waitFor(() => {
-      // Query for 'From invoices' link again after navigation - it should not exist
-      expect(
-        screen.queryByRole('link', { name: 'From invoices' }),
-      ).not.toBeInTheDocument()
-    })
+    // Query for 'From invoices' link again after navigation - it should not exist
+    expect(
+      screen.queryByRole('link', { name: 'From invoices' }),
+    ).not.toBeInTheDocument()
 
     expect(ErrorComponent).not.toHaveBeenCalled()
   })
@@ -5725,6 +5722,8 @@ describe('relative links to current route', () => {
       render(<RouterProvider router={router} />)
 
       const postButton = await screen.findByTestId('posts-link')
+      const searchButton = await screen.findByTestId('search-link')
+      const searchButton2 = await screen.findByTestId('search2-link')
 
       fireEvent.click(postButton)
 
@@ -5732,15 +5731,6 @@ describe('relative links to current route', () => {
         expect(window.location.pathname).toBe(`/post${tail}`)
       })
 
-      // Wait for Vue to update the Links with new hrefs after navigation
-      await waitFor(() => {
-        const searchLink = screen.getByTestId('search-link')
-        expect(searchLink.getAttribute('href')).toContain('/post')
-      })
-
-      const searchButton = await screen.findByTestId('search-link')
-      const searchButton2 = await screen.findByTestId('search2-link')
-
       fireEvent.click(searchButton)
 
       await waitFor(() => {
diff --git a/packages/vue-router/tests/store-updates-during-navigation.test.tsx b/packages/vue-router/tests/store-updates-during-navigation.test.tsx
index d0b0d82c4b..6cf44c3725 100644
--- a/packages/vue-router/tests/store-updates-during-navigation.test.tsx
+++ b/packages/vue-router/tests/store-updates-during-navigation.test.tsx
@@ -138,7 +138,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
     // that needs to be done during a navigation.
     // Any change that increases this number should be investigated.
     // Note: Vue has different update counts than React/Solid due to different reactivity
-    expect(updates).toBe(28)
+    expect(updates).toBe(27)
   })
 
   test('redirection in preload', async () => {
@@ -174,7 +174,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
     // that needs to be done during a navigation.
     // Any change that increases this number should be investigated.
     // Note: Vue has different update counts than React/Solid due to different reactivity
-    expect(updates).toBe(26)
+    expect(updates).toBe(25)
   })
 
   test('nothing', async () => {
@@ -204,7 +204,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
     // that needs to be done during a navigation.
     // Any change that increases this number should be investigated.
     // Note: Vue has different update counts than React/Solid due to different reactivity
-    expect(updates).toBe(23)
+    expect(updates).toBe(22)
   })
 
   test('hover preload, then navigate, w/ async loaders', async () => {
