diff --git a/packages/global.d.ts b/packages/global.d.ts
index f53d7b71acd..65f36d34775 100644
--- a/packages/global.d.ts
+++ b/packages/global.d.ts
@@ -17,6 +17,7 @@ declare var __COMPAT__: boolean
 declare var __FEATURE_OPTIONS_API__: boolean
 declare var __FEATURE_PROD_DEVTOOLS__: boolean
 declare var __FEATURE_SUSPENSE__: boolean
+declare var __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: boolean
 
 // for tests
 declare namespace jest {
diff --git a/packages/runtime-core/src/featureFlags.ts b/packages/runtime-core/src/featureFlags.ts
index e878407bcc8..267e69eef5c 100644
--- a/packages/runtime-core/src/featureFlags.ts
+++ b/packages/runtime-core/src/featureFlags.ts
@@ -20,6 +20,11 @@ export function initFeatureFlags() {
     getGlobalThis().__VUE_PROD_DEVTOOLS__ = false
   }
 
+  if (typeof __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__ !== 'boolean') {
+    __DEV__ && needWarn.push(`__VUE_PROD_HYDRATION_MISMATCH_DETAILS__`)
+    getGlobalThis().__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ = false
+  }
+
   if (__DEV__ && needWarn.length) {
     const multi = needWarn.length > 1
     console.warn(
diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts
index 35ab851953a..245d586a2c3 100644
--- a/packages/runtime-core/src/hydration.ts
+++ b/packages/runtime-core/src/hydration.ts
@@ -81,7 +81,7 @@ export function createHydrationFunctions(
 
   const hydrate: RootHydrateFunction = (vnode, container) => {
     if (!container.hasChildNodes()) {
-      __DEV__ &&
+      ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
         warn(
           `Attempting to hydrate existing markup but container is empty. ` +
             `Performing full mount instead.`
@@ -159,7 +159,7 @@ export function createHydrationFunctions(
         } else {
           if ((node as Text).data !== vnode.children) {
             hasMismatch = true
-            __DEV__ &&
+            ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
               warn(
                 `Hydration text mismatch in`,
                 node.parentNode,
@@ -326,7 +326,7 @@ export function createHydrationFunctions(
             rendererInternals,
             hydrateNode
           )
-        } else if (__DEV__) {
+        } else if (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) {
           warn('Invalid HostVNode type:', type, `(${typeof type})`)
         }
     }
@@ -398,7 +398,10 @@ export function createHydrationFunctions(
         let hasWarned = false
         while (next) {
           hasMismatch = true
-          if (__DEV__ && !hasWarned) {
+          if (
+            (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
+            !hasWarned
+          ) {
             warn(
               `Hydration children mismatch on`,
               el,
@@ -414,7 +417,7 @@ export function createHydrationFunctions(
       } else if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
         if (el.textContent !== vnode.children) {
           hasMismatch = true
-          __DEV__ &&
+          ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
             warn(
               `Hydration text content mismatch on`,
               el,
@@ -525,7 +528,10 @@ export function createHydrationFunctions(
         continue
       } else {
         hasMismatch = true
-        if (__DEV__ && !hasWarned) {
+        if (
+          (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
+          !hasWarned
+        ) {
           warn(
             `Hydration children mismatch on`,
             container,
@@ -595,7 +601,7 @@ export function createHydrationFunctions(
     isFragment: boolean
   ): Node | null => {
     hasMismatch = true
-    __DEV__ &&
+    ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
       warn(
         `Hydration node mismatch:\n- Client vnode:`,
         vnode.type,
diff --git a/packages/vue/README.md b/packages/vue/README.md
index a98bd997487..c41162cc1c6 100644
--- a/packages/vue/README.md
+++ b/packages/vue/README.md
@@ -37,6 +37,7 @@ Starting with 3.0.0-rc.3, `esm-bundler` builds now exposes global feature flags
 
 - `__VUE_OPTIONS_API__` (enable/disable Options API support, default: `true`)
 - `__VUE_PROD_DEVTOOLS__` (enable/disable devtools support in production, default: `false`)
+- `__VUE_PROD_HYDRATION_MISMATCH_DETAILS__` (enable/disable detailed warnings for hydration mismatches in production, default: `false`)
 
 The build will work without configuring these flags, however it is **strongly recommended** to properly configure them in order to get proper tree-shaking in the final bundle. To configure these flags:
 
diff --git a/rollup.config.js b/rollup.config.js
index b7d38e4527a..3703faae280 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -180,6 +180,9 @@ function createConfig(format, output, plugins = []) {
         : `true`,
       __FEATURE_PROD_DEVTOOLS__: isBundlerESMBuild
         ? `__VUE_PROD_DEVTOOLS__`
+        : `false`,
+      __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: isBundlerESMBuild
+        ? `__VUE_PROD_HYDRATION_MISMATCH_DETAILS__`
         : `false`
     }
 
diff --git a/scripts/dev.js b/scripts/dev.js
index 4820723778d..5f996a29831 100644
--- a/scripts/dev.js
+++ b/scripts/dev.js
@@ -124,7 +124,8 @@ esbuild
       __COMPAT__: String(target === 'vue-compat'),
       __FEATURE_SUSPENSE__: `true`,
       __FEATURE_OPTIONS_API__: `true`,
-      __FEATURE_PROD_DEVTOOLS__: `false`
+      __FEATURE_PROD_DEVTOOLS__: `false`,
+      __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: `false`
     }
   })
   .then(ctx => ctx.watch())
diff --git a/scripts/usage-size.ts b/scripts/usage-size.ts
index 1a1013b7847..31ee85daebb 100644
--- a/scripts/usage-size.ts
+++ b/scripts/usage-size.ts
@@ -71,6 +71,7 @@ async function generateBundle(preset: Preset) {
       replace({
         'process.env.NODE_ENV': '"production"',
         __VUE_PROD_DEVTOOLS__: 'false',
+        __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false',
         __VUE_OPTIONS_API__: 'true',
         preventAssignment: true
       })
diff --git a/vitest.config.ts b/vitest.config.ts
index e5d5f59345f..ced861a0373 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -15,6 +15,7 @@ export default defineConfig({
     __FEATURE_OPTIONS_API__: true,
     __FEATURE_SUSPENSE__: true,
     __FEATURE_PROD_DEVTOOLS__: false,
+    __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
     __COMPAT__: true
   },
   resolve: {