diff --git a/packages/runtime-core/__tests__/hydration.spec.ts b/packages/runtime-core/__tests__/hydration.spec.ts
index 6caa2442e18..e0277622c13 100644
--- a/packages/runtime-core/__tests__/hydration.spec.ts
+++ b/packages/runtime-core/__tests__/hydration.spec.ts
@@ -7,7 +7,10 @@ import {
   Teleport,
   Transition,
   type VNode,
+  createBlock,
   createCommentVNode,
+  createElementBlock,
+  createElementVNode,
   createSSRApp,
   createStaticVNode,
   createTextVNode,
@@ -17,16 +20,19 @@ import {
   h,
   nextTick,
   onMounted,
+  openBlock,
   ref,
   renderSlot,
   useCssVars,
   vModelCheckbox,
   vShow,
+  withCtx,
   withDirectives,
 } from '@vue/runtime-dom'
 import { type SSRContext, renderToString } from '@vue/server-renderer'
 import { PatchFlags } from '@vue/shared'
 import { vShowOriginalDisplay } from '../../runtime-dom/src/directives/vShow'
+import { expect } from 'vitest'
 
 function mountWithHydration(html: string, render: () => any) {
   const container = document.createElement('div')
@@ -1292,6 +1298,81 @@ describe('SSR hydration', () => {
     `)
   })
 
+  // #10607
+  test('update component stable slot (prod + optimized mode)', async () => {
+    __DEV__ = false
+    const container = document.createElement('div')
+    container.innerHTML = `<template><div show="false"><!--[--><div><div><!----></div></div><div>0</div><!--]--></div></template>`
+    const Comp = {
+      render(this: any) {
+        return (
+          openBlock(),
+          createElementBlock('div', null, [renderSlot(this.$slots, 'default')])
+        )
+      },
+    }
+    const show = ref(false)
+    const clicked = ref(false)
+
+    const Wrapper = {
+      setup() {
+        const items = ref<number[]>([])
+        onMounted(() => {
+          items.value = [1]
+        })
+        return () => {
+          return (
+            openBlock(),
+            createBlock(Comp, null, {
+              default: withCtx(() => [
+                createElementVNode('div', null, [
+                  createElementVNode('div', null, [
+                    clicked.value
+                      ? (openBlock(),
+                        createElementBlock('div', { key: 0 }, 'foo'))
+                      : createCommentVNode('v-if', true),
+                  ]),
+                ]),
+                createElementVNode(
+                  'div',
+                  null,
+                  items.value.length,
+                  1 /* TEXT */,
+                ),
+              ]),
+              _: 1 /* STABLE */,
+            })
+          )
+        }
+      },
+    }
+    createSSRApp({
+      components: { Wrapper },
+      data() {
+        return { show }
+      },
+      template: `<Wrapper :show="show"/>`,
+    }).mount(container)
+
+    await nextTick()
+    expect(container.innerHTML).toBe(
+      `<div show="false"><!--[--><div><div><!----></div></div><div>1</div><!--]--></div>`,
+    )
+
+    show.value = true
+    await nextTick()
+    expect(async () => {
+      clicked.value = true
+      await nextTick()
+    }).not.toThrow("Cannot read properties of null (reading 'insertBefore')")
+
+    await nextTick()
+    expect(container.innerHTML).toBe(
+      `<div show="true"><!--[--><div><div><div>foo</div></div></div><div>1</div><!--]--></div>`,
+    )
+    __DEV__ = true
+  })
+
   describe('mismatch handling', () => {
     test('text node', () => {
       const { container } = mountWithHydration(`foo`, () => 'bar')
diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts
index 8469577608e..a7832ac3d57 100644
--- a/packages/runtime-core/src/hydration.ts
+++ b/packages/runtime-core/src/hydration.ts
@@ -120,6 +120,7 @@ export function createHydrationFunctions(
     slotScopeIds: string[] | null,
     optimized = false,
   ): Node | null => {
+    optimized = optimized || !!vnode.dynamicChildren
     const isFragmentStart = isComment(node) && node.data === '['
     const onMismatch = () =>
       handleMismatch(