diff --git a/packages/react-dom/src/events/ReactDOMEventListener.js b/packages/react-dom/src/events/ReactDOMEventListener.js
index 5066cc005a0c6..2e6c02daffa94 100644
--- a/packages/react-dom/src/events/ReactDOMEventListener.js
+++ b/packages/react-dom/src/events/ReactDOMEventListener.js
@@ -38,7 +38,10 @@ import {
 import getEventTarget from './getEventTarget';
 import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';
 
-import {enableLegacyFBSupport} from 'shared/ReactFeatureFlags';
+import {
+  enableLegacyFBSupport,
+  decoupleUpdatePriorityFromScheduler,
+} from 'shared/ReactFeatureFlags';
 import {
   UserBlockingEvent,
   ContinuousEvent,
@@ -147,10 +150,25 @@ function dispatchUserBlockingUpdate(
   container,
   nativeEvent,
 ) {
-  // TODO: Double wrapping is necessary while we decouple Scheduler priority.
-  const previousPriority = getCurrentUpdateLanePriority();
-  try {
-    setCurrentUpdateLanePriority(InputContinuousLanePriority);
+  if (decoupleUpdatePriorityFromScheduler) {
+    const previousPriority = getCurrentUpdateLanePriority();
+    try {
+      // TODO: Double wrapping is necessary while we decouple Scheduler priority.
+      setCurrentUpdateLanePriority(InputContinuousLanePriority);
+      runWithPriority(
+        UserBlockingPriority,
+        dispatchEvent.bind(
+          null,
+          domEventName,
+          eventSystemFlags,
+          container,
+          nativeEvent,
+        ),
+      );
+    } finally {
+      setCurrentUpdateLanePriority(previousPriority);
+    }
+  } else {
     runWithPriority(
       UserBlockingPriority,
       dispatchEvent.bind(
@@ -161,8 +179,6 @@ function dispatchUserBlockingUpdate(
         nativeEvent,
       ),
     );
-  } finally {
-    setCurrentUpdateLanePriority(previousPriority);
   }
 }
 
diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js
index 0f1309ff70b02..99f367f606873 100644
--- a/packages/react-reconciler/src/ReactFiberHooks.new.js
+++ b/packages/react-reconciler/src/ReactFiberHooks.new.js
@@ -26,6 +26,7 @@ import {
   enableDebugTracing,
   enableSchedulingProfiler,
   enableNewReconciler,
+  decoupleUpdatePriorityFromScheduler,
 } from 'shared/ReactFeatureFlags';
 
 import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode';
@@ -1506,34 +1507,64 @@ function rerenderDeferredValue<T>(
 
 function startTransition(setPending, config, callback) {
   const priorityLevel = getCurrentPriorityLevel();
-  const previousLanePriority = getCurrentUpdateLanePriority();
-  setCurrentUpdateLanePriority(
-    higherLanePriority(previousLanePriority, InputContinuousLanePriority),
-  );
-  runWithPriority(
-    priorityLevel < UserBlockingPriority ? UserBlockingPriority : priorityLevel,
-    () => {
-      setPending(true);
-    },
-  );
+  if (decoupleUpdatePriorityFromScheduler) {
+    const previousLanePriority = getCurrentUpdateLanePriority();
+    setCurrentUpdateLanePriority(
+      higherLanePriority(previousLanePriority, InputContinuousLanePriority),
+    );
 
-  // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition.
-  setCurrentUpdateLanePriority(DefaultLanePriority);
+    runWithPriority(
+      priorityLevel < UserBlockingPriority
+        ? UserBlockingPriority
+        : priorityLevel,
+      () => {
+        setPending(true);
+      },
+    );
 
-  runWithPriority(
-    priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
-    () => {
-      const previousConfig = ReactCurrentBatchConfig.suspense;
-      ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
-      try {
-        setPending(false);
-        callback();
-      } finally {
-        setCurrentUpdateLanePriority(previousLanePriority);
-        ReactCurrentBatchConfig.suspense = previousConfig;
-      }
-    },
-  );
+    // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition.
+    setCurrentUpdateLanePriority(DefaultLanePriority);
+
+    runWithPriority(
+      priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
+      () => {
+        const previousConfig = ReactCurrentBatchConfig.suspense;
+        ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
+        try {
+          setPending(false);
+          callback();
+        } finally {
+          if (decoupleUpdatePriorityFromScheduler) {
+            setCurrentUpdateLanePriority(previousLanePriority);
+          }
+          ReactCurrentBatchConfig.suspense = previousConfig;
+        }
+      },
+    );
+  } else {
+    runWithPriority(
+      priorityLevel < UserBlockingPriority
+        ? UserBlockingPriority
+        : priorityLevel,
+      () => {
+        setPending(true);
+      },
+    );
+
+    runWithPriority(
+      priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
+      () => {
+        const previousConfig = ReactCurrentBatchConfig.suspense;
+        ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
+        try {
+          setPending(false);
+          callback();
+        } finally {
+          ReactCurrentBatchConfig.suspense = previousConfig;
+        }
+      },
+    );
+  }
 }
 
 function mountTransition(
diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js
index 328ae20d67546..380524df9aad6 100644
--- a/packages/react-reconciler/src/ReactFiberHooks.old.js
+++ b/packages/react-reconciler/src/ReactFiberHooks.old.js
@@ -26,6 +26,7 @@ import {
   enableDebugTracing,
   enableSchedulingProfiler,
   enableNewReconciler,
+  decoupleUpdatePriorityFromScheduler,
 } from 'shared/ReactFeatureFlags';
 
 import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode';
@@ -1505,34 +1506,64 @@ function rerenderDeferredValue<T>(
 
 function startTransition(setPending, config, callback) {
   const priorityLevel = getCurrentPriorityLevel();
-  const previousLanePriority = getCurrentUpdateLanePriority();
-  setCurrentUpdateLanePriority(
-    higherLanePriority(previousLanePriority, InputContinuousLanePriority),
-  );
-  runWithPriority(
-    priorityLevel < UserBlockingPriority ? UserBlockingPriority : priorityLevel,
-    () => {
-      setPending(true);
-    },
-  );
+  if (decoupleUpdatePriorityFromScheduler) {
+    const previousLanePriority = getCurrentUpdateLanePriority();
+    setCurrentUpdateLanePriority(
+      higherLanePriority(previousLanePriority, InputContinuousLanePriority),
+    );
 
-  // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition.
-  setCurrentUpdateLanePriority(DefaultLanePriority);
+    runWithPriority(
+      priorityLevel < UserBlockingPriority
+        ? UserBlockingPriority
+        : priorityLevel,
+      () => {
+        setPending(true);
+      },
+    );
 
-  runWithPriority(
-    priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
-    () => {
-      const previousConfig = ReactCurrentBatchConfig.suspense;
-      ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
-      try {
-        setPending(false);
-        callback();
-      } finally {
-        setCurrentUpdateLanePriority(previousLanePriority);
-        ReactCurrentBatchConfig.suspense = previousConfig;
-      }
-    },
-  );
+    // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition.
+    setCurrentUpdateLanePriority(DefaultLanePriority);
+
+    runWithPriority(
+      priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
+      () => {
+        const previousConfig = ReactCurrentBatchConfig.suspense;
+        ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
+        try {
+          setPending(false);
+          callback();
+        } finally {
+          if (decoupleUpdatePriorityFromScheduler) {
+            setCurrentUpdateLanePriority(previousLanePriority);
+          }
+          ReactCurrentBatchConfig.suspense = previousConfig;
+        }
+      },
+    );
+  } else {
+    runWithPriority(
+      priorityLevel < UserBlockingPriority
+        ? UserBlockingPriority
+        : priorityLevel,
+      () => {
+        setPending(true);
+      },
+    );
+
+    runWithPriority(
+      priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
+      () => {
+        const previousConfig = ReactCurrentBatchConfig.suspense;
+        ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
+        try {
+          setPending(false);
+          callback();
+        } finally {
+          ReactCurrentBatchConfig.suspense = previousConfig;
+        }
+      },
+    );
+  }
 }
 
 function mountTransition(
diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
index 63ffe2d356aae..9cd162cb01cf0 100644
--- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
@@ -1163,13 +1163,16 @@ export function flushDiscreteUpdates() {
 }
 
 export function deferredUpdates<A>(fn: () => A): A {
-  // TODO: Remove in favor of Scheduler.next
-  const previousLanePriority = getCurrentUpdateLanePriority();
-  try {
-    setCurrentUpdateLanePriority(DefaultLanePriority);
+  if (decoupleUpdatePriorityFromScheduler) {
+    const previousLanePriority = getCurrentUpdateLanePriority();
+    try {
+      setCurrentUpdateLanePriority(DefaultLanePriority);
+      return runWithPriority(NormalSchedulerPriority, fn);
+    } finally {
+      setCurrentUpdateLanePriority(previousLanePriority);
+    }
+  } else {
     return runWithPriority(NormalSchedulerPriority, fn);
-  } finally {
-    setCurrentUpdateLanePriority(previousLanePriority);
   }
 }
 
@@ -1225,20 +1228,35 @@ export function discreteUpdates<A, B, C, D, R>(
 ): R {
   const prevExecutionContext = executionContext;
   executionContext |= DiscreteEventContext;
-  const previousLanePriority = getCurrentUpdateLanePriority();
-  try {
-    setCurrentUpdateLanePriority(InputDiscreteLanePriority);
-    // Should this
-    return runWithPriority(
-      UserBlockingSchedulerPriority,
-      fn.bind(null, a, b, c, d),
-    );
-  } finally {
-    setCurrentUpdateLanePriority(previousLanePriority);
-    executionContext = prevExecutionContext;
-    if (executionContext === NoContext) {
-      // Flush the immediate callbacks that were scheduled during this batch
-      flushSyncCallbackQueue();
+
+  if (decoupleUpdatePriorityFromScheduler) {
+    const previousLanePriority = getCurrentUpdateLanePriority();
+    try {
+      setCurrentUpdateLanePriority(InputDiscreteLanePriority);
+      return runWithPriority(
+        UserBlockingSchedulerPriority,
+        fn.bind(null, a, b, c, d),
+      );
+    } finally {
+      setCurrentUpdateLanePriority(previousLanePriority);
+      executionContext = prevExecutionContext;
+      if (executionContext === NoContext) {
+        // Flush the immediate callbacks that were scheduled during this batch
+        flushSyncCallbackQueue();
+      }
+    }
+  } else {
+    try {
+      return runWithPriority(
+        UserBlockingSchedulerPriority,
+        fn.bind(null, a, b, c, d),
+      );
+    } finally {
+      executionContext = prevExecutionContext;
+      if (executionContext === NoContext) {
+        // Flush the immediate callbacks that were scheduled during this batch
+        flushSyncCallbackQueue();
+      }
     }
   }
 }
@@ -1271,37 +1289,67 @@ export function flushSync<A, R>(fn: A => R, a: A): R {
     return fn(a);
   }
   executionContext |= BatchedContext;
-  const previousLanePriority = getCurrentUpdateLanePriority();
-  try {
-    setCurrentUpdateLanePriority(SyncLanePriority);
-    if (fn) {
-      return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
-    } else {
-      return (undefined: $FlowFixMe);
+
+  if (decoupleUpdatePriorityFromScheduler) {
+    const previousLanePriority = getCurrentUpdateLanePriority();
+    try {
+      setCurrentUpdateLanePriority(SyncLanePriority);
+      if (fn) {
+        return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
+      } else {
+        return (undefined: $FlowFixMe);
+      }
+    } finally {
+      setCurrentUpdateLanePriority(previousLanePriority);
+      executionContext = prevExecutionContext;
+      // Flush the immediate callbacks that were scheduled during this batch.
+      // Note that this will happen even if batchedUpdates is higher up
+      // the stack.
+      flushSyncCallbackQueue();
+    }
+  } else {
+    try {
+      if (fn) {
+        return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
+      } else {
+        return (undefined: $FlowFixMe);
+      }
+    } finally {
+      executionContext = prevExecutionContext;
+      // Flush the immediate callbacks that were scheduled during this batch.
+      // Note that this will happen even if batchedUpdates is higher up
+      // the stack.
+      flushSyncCallbackQueue();
     }
-  } finally {
-    setCurrentUpdateLanePriority(previousLanePriority);
-    executionContext = prevExecutionContext;
-    // Flush the immediate callbacks that were scheduled during this batch.
-    // Note that this will happen even if batchedUpdates is higher up
-    // the stack.
-    flushSyncCallbackQueue();
   }
 }
 
 export function flushControlled(fn: () => mixed): void {
   const prevExecutionContext = executionContext;
   executionContext |= BatchedContext;
-  const previousLanePriority = getCurrentUpdateLanePriority();
-  try {
-    setCurrentUpdateLanePriority(SyncLanePriority);
-    runWithPriority(ImmediateSchedulerPriority, fn);
-  } finally {
-    setCurrentUpdateLanePriority(previousLanePriority);
-    executionContext = prevExecutionContext;
-    if (executionContext === NoContext) {
-      // Flush the immediate callbacks that were scheduled during this batch
-      flushSyncCallbackQueue();
+  if (decoupleUpdatePriorityFromScheduler) {
+    const previousLanePriority = getCurrentUpdateLanePriority();
+    try {
+      setCurrentUpdateLanePriority(SyncLanePriority);
+      runWithPriority(ImmediateSchedulerPriority, fn);
+    } finally {
+      setCurrentUpdateLanePriority(previousLanePriority);
+
+      executionContext = prevExecutionContext;
+      if (executionContext === NoContext) {
+        // Flush the immediate callbacks that were scheduled during this batch
+        flushSyncCallbackQueue();
+      }
+    }
+  } else {
+    try {
+      runWithPriority(ImmediateSchedulerPriority, fn);
+    } finally {
+      executionContext = prevExecutionContext;
+      if (executionContext === NoContext) {
+        // Flush the immediate callbacks that were scheduled during this batch
+        flushSyncCallbackQueue();
+      }
     }
   }
 }
@@ -2122,8 +2170,11 @@ function commitRootImpl(root, renderPriorityLevel) {
   }
 
   if (firstEffect !== null) {
-    const previousLanePriority = getCurrentUpdateLanePriority();
-    setCurrentUpdateLanePriority(SyncLanePriority);
+    let previousLanePriority;
+    if (decoupleUpdatePriorityFromScheduler) {
+      previousLanePriority = getCurrentUpdateLanePriority();
+      setCurrentUpdateLanePriority(SyncLanePriority);
+    }
 
     const prevExecutionContext = executionContext;
     executionContext |= CommitContext;
@@ -2214,8 +2265,10 @@ function commitRootImpl(root, renderPriorityLevel) {
     }
     executionContext = prevExecutionContext;
 
-    // Reset the priority to the previous non-sync value.
-    setCurrentUpdateLanePriority(previousLanePriority);
+    if (decoupleUpdatePriorityFromScheduler && previousLanePriority != null) {
+      // Reset the priority to the previous non-sync value.
+      setCurrentUpdateLanePriority(previousLanePriority);
+    }
   } else {
     // No effects.
     root.current = finishedWork;
@@ -2655,14 +2708,18 @@ export function flushPassiveEffects(): boolean {
         ? NormalSchedulerPriority
         : pendingPassiveEffectsRenderPriority;
     pendingPassiveEffectsRenderPriority = NoSchedulerPriority;
-    const previousLanePriority = getCurrentUpdateLanePriority();
-    try {
-      setCurrentUpdateLanePriority(
-        schedulerPriorityToLanePriority(priorityLevel),
-      );
+    if (decoupleUpdatePriorityFromScheduler) {
+      const previousLanePriority = getCurrentUpdateLanePriority();
+      try {
+        setCurrentUpdateLanePriority(
+          schedulerPriorityToLanePriority(priorityLevel),
+        );
+        return runWithPriority(priorityLevel, flushPassiveEffectsImpl);
+      } finally {
+        setCurrentUpdateLanePriority(previousLanePriority);
+      }
+    } else {
       return runWithPriority(priorityLevel, flushPassiveEffectsImpl);
-    } finally {
-      setCurrentUpdateLanePriority(previousLanePriority);
     }
   }
   return false;
diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
index 36670a257f0ec..4cb6e5093377e 100644
--- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
@@ -1147,13 +1147,16 @@ export function flushDiscreteUpdates() {
 }
 
 export function deferredUpdates<A>(fn: () => A): A {
-  // TODO: Remove in favor of Scheduler.next
-  const previousLanePriority = getCurrentUpdateLanePriority();
-  try {
-    setCurrentUpdateLanePriority(DefaultLanePriority);
+  if (decoupleUpdatePriorityFromScheduler) {
+    const previousLanePriority = getCurrentUpdateLanePriority();
+    try {
+      setCurrentUpdateLanePriority(DefaultLanePriority);
+      return runWithPriority(NormalSchedulerPriority, fn);
+    } finally {
+      setCurrentUpdateLanePriority(previousLanePriority);
+    }
+  } else {
     return runWithPriority(NormalSchedulerPriority, fn);
-  } finally {
-    setCurrentUpdateLanePriority(previousLanePriority);
   }
 }
 
@@ -1209,20 +1212,35 @@ export function discreteUpdates<A, B, C, D, R>(
 ): R {
   const prevExecutionContext = executionContext;
   executionContext |= DiscreteEventContext;
-  const previousLanePriority = getCurrentUpdateLanePriority();
-  try {
-    setCurrentUpdateLanePriority(InputDiscreteLanePriority);
-    // Should this
-    return runWithPriority(
-      UserBlockingSchedulerPriority,
-      fn.bind(null, a, b, c, d),
-    );
-  } finally {
-    setCurrentUpdateLanePriority(previousLanePriority);
-    executionContext = prevExecutionContext;
-    if (executionContext === NoContext) {
-      // Flush the immediate callbacks that were scheduled during this batch
-      flushSyncCallbackQueue();
+
+  if (decoupleUpdatePriorityFromScheduler) {
+    const previousLanePriority = getCurrentUpdateLanePriority();
+    try {
+      setCurrentUpdateLanePriority(InputDiscreteLanePriority);
+      return runWithPriority(
+        UserBlockingSchedulerPriority,
+        fn.bind(null, a, b, c, d),
+      );
+    } finally {
+      setCurrentUpdateLanePriority(previousLanePriority);
+      executionContext = prevExecutionContext;
+      if (executionContext === NoContext) {
+        // Flush the immediate callbacks that were scheduled during this batch
+        flushSyncCallbackQueue();
+      }
+    }
+  } else {
+    try {
+      return runWithPriority(
+        UserBlockingSchedulerPriority,
+        fn.bind(null, a, b, c, d),
+      );
+    } finally {
+      executionContext = prevExecutionContext;
+      if (executionContext === NoContext) {
+        // Flush the immediate callbacks that were scheduled during this batch
+        flushSyncCallbackQueue();
+      }
     }
   }
 }
@@ -1255,37 +1273,67 @@ export function flushSync<A, R>(fn: A => R, a: A): R {
     return fn(a);
   }
   executionContext |= BatchedContext;
-  const previousLanePriority = getCurrentUpdateLanePriority();
-  try {
-    setCurrentUpdateLanePriority(SyncLanePriority);
-    if (fn) {
-      return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
-    } else {
-      return (undefined: $FlowFixMe);
+
+  if (decoupleUpdatePriorityFromScheduler) {
+    const previousLanePriority = getCurrentUpdateLanePriority();
+    try {
+      setCurrentUpdateLanePriority(SyncLanePriority);
+      if (fn) {
+        return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
+      } else {
+        return (undefined: $FlowFixMe);
+      }
+    } finally {
+      setCurrentUpdateLanePriority(previousLanePriority);
+      executionContext = prevExecutionContext;
+      // Flush the immediate callbacks that were scheduled during this batch.
+      // Note that this will happen even if batchedUpdates is higher up
+      // the stack.
+      flushSyncCallbackQueue();
+    }
+  } else {
+    try {
+      if (fn) {
+        return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
+      } else {
+        return (undefined: $FlowFixMe);
+      }
+    } finally {
+      executionContext = prevExecutionContext;
+      // Flush the immediate callbacks that were scheduled during this batch.
+      // Note that this will happen even if batchedUpdates is higher up
+      // the stack.
+      flushSyncCallbackQueue();
     }
-  } finally {
-    setCurrentUpdateLanePriority(previousLanePriority);
-    executionContext = prevExecutionContext;
-    // Flush the immediate callbacks that were scheduled during this batch.
-    // Note that this will happen even if batchedUpdates is higher up
-    // the stack.
-    flushSyncCallbackQueue();
   }
 }
 
 export function flushControlled(fn: () => mixed): void {
   const prevExecutionContext = executionContext;
   executionContext |= BatchedContext;
-  const previousLanePriority = getCurrentUpdateLanePriority();
-  try {
-    setCurrentUpdateLanePriority(SyncLanePriority);
-    runWithPriority(ImmediateSchedulerPriority, fn);
-  } finally {
-    setCurrentUpdateLanePriority(previousLanePriority);
-    executionContext = prevExecutionContext;
-    if (executionContext === NoContext) {
-      // Flush the immediate callbacks that were scheduled during this batch
-      flushSyncCallbackQueue();
+  if (decoupleUpdatePriorityFromScheduler) {
+    const previousLanePriority = getCurrentUpdateLanePriority();
+    try {
+      setCurrentUpdateLanePriority(SyncLanePriority);
+      runWithPriority(ImmediateSchedulerPriority, fn);
+    } finally {
+      setCurrentUpdateLanePriority(previousLanePriority);
+
+      executionContext = prevExecutionContext;
+      if (executionContext === NoContext) {
+        // Flush the immediate callbacks that were scheduled during this batch
+        flushSyncCallbackQueue();
+      }
+    }
+  } else {
+    try {
+      runWithPriority(ImmediateSchedulerPriority, fn);
+    } finally {
+      executionContext = prevExecutionContext;
+      if (executionContext === NoContext) {
+        // Flush the immediate callbacks that were scheduled during this batch
+        flushSyncCallbackQueue();
+      }
     }
   }
 }
@@ -2019,8 +2067,11 @@ function commitRootImpl(root, renderPriorityLevel) {
   }
 
   if (firstEffect !== null) {
-    const previousLanePriority = getCurrentUpdateLanePriority();
-    setCurrentUpdateLanePriority(SyncLanePriority);
+    let previousLanePriority;
+    if (decoupleUpdatePriorityFromScheduler) {
+      previousLanePriority = getCurrentUpdateLanePriority();
+      setCurrentUpdateLanePriority(SyncLanePriority);
+    }
 
     const prevExecutionContext = executionContext;
     executionContext |= CommitContext;
@@ -2143,8 +2194,10 @@ function commitRootImpl(root, renderPriorityLevel) {
     }
     executionContext = prevExecutionContext;
 
-    // Reset the priority to the previous non-sync value.
-    setCurrentUpdateLanePriority(previousLanePriority);
+    if (decoupleUpdatePriorityFromScheduler && previousLanePriority != null) {
+      // Reset the priority to the previous non-sync value.
+      setCurrentUpdateLanePriority(previousLanePriority);
+    }
   } else {
     // No effects.
     root.current = finishedWork;
@@ -2463,14 +2516,18 @@ export function flushPassiveEffects(): boolean {
         ? NormalSchedulerPriority
         : pendingPassiveEffectsRenderPriority;
     pendingPassiveEffectsRenderPriority = NoSchedulerPriority;
-    const previousLanePriority = getCurrentUpdateLanePriority();
-    try {
-      setCurrentUpdateLanePriority(
-        schedulerPriorityToLanePriority(priorityLevel),
-      );
+    if (decoupleUpdatePriorityFromScheduler) {
+      const previousLanePriority = getCurrentUpdateLanePriority();
+      try {
+        setCurrentUpdateLanePriority(
+          schedulerPriorityToLanePriority(priorityLevel),
+        );
+        return runWithPriority(priorityLevel, flushPassiveEffectsImpl);
+      } finally {
+        setCurrentUpdateLanePriority(previousLanePriority);
+      }
+    } else {
       return runWithPriority(priorityLevel, flushPassiveEffectsImpl);
-    } finally {
-      setCurrentUpdateLanePriority(previousLanePriority);
     }
   }
   return false;
diff --git a/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js b/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js
index 99780f6dbaff3..18e4ba82ab36c 100644
--- a/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js
+++ b/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js
@@ -13,7 +13,10 @@ import type {ReactPriorityLevel} from './ReactInternalTypes';
 // CommonJS interop named imports.
 import * as Scheduler from 'scheduler';
 import {__interactionsRef} from 'scheduler/tracing';
-import {enableSchedulerTracing} from 'shared/ReactFeatureFlags';
+import {
+  enableSchedulerTracing,
+  decoupleUpdatePriorityFromScheduler,
+} from 'shared/ReactFeatureFlags';
 import invariant from 'shared/invariant';
 import {
   SyncLanePriority,
@@ -176,34 +179,63 @@ function flushSyncCallbackQueueImpl() {
     // Prevent re-entrancy.
     isFlushingSyncQueue = true;
     let i = 0;
-    const previousLanePriority = getCurrentUpdateLanePriority();
-    try {
-      const isSync = true;
-      const queue = syncQueue;
-      setCurrentUpdateLanePriority(SyncLanePriority);
-      runWithPriority(ImmediatePriority, () => {
-        for (; i < queue.length; i++) {
-          let callback = queue[i];
-          do {
-            callback = callback(isSync);
-          } while (callback !== null);
+    if (decoupleUpdatePriorityFromScheduler) {
+      const previousLanePriority = getCurrentUpdateLanePriority();
+      try {
+        const isSync = true;
+        const queue = syncQueue;
+        setCurrentUpdateLanePriority(SyncLanePriority);
+        runWithPriority(ImmediatePriority, () => {
+          for (; i < queue.length; i++) {
+            let callback = queue[i];
+            do {
+              callback = callback(isSync);
+            } while (callback !== null);
+          }
+        });
+        syncQueue = null;
+      } catch (error) {
+        // If something throws, leave the remaining callbacks on the queue.
+        if (syncQueue !== null) {
+          syncQueue = syncQueue.slice(i + 1);
+        }
+        // Resume flushing in the next tick
+        Scheduler_scheduleCallback(
+          Scheduler_ImmediatePriority,
+          flushSyncCallbackQueue,
+        );
+        throw error;
+      } finally {
+        setCurrentUpdateLanePriority(previousLanePriority);
+        isFlushingSyncQueue = false;
+      }
+    } else {
+      try {
+        const isSync = true;
+        const queue = syncQueue;
+        runWithPriority(ImmediatePriority, () => {
+          for (; i < queue.length; i++) {
+            let callback = queue[i];
+            do {
+              callback = callback(isSync);
+            } while (callback !== null);
+          }
+        });
+        syncQueue = null;
+      } catch (error) {
+        // If something throws, leave the remaining callbacks on the queue.
+        if (syncQueue !== null) {
+          syncQueue = syncQueue.slice(i + 1);
         }
-      });
-      syncQueue = null;
-    } catch (error) {
-      // If something throws, leave the remaining callbacks on the queue.
-      if (syncQueue !== null) {
-        syncQueue = syncQueue.slice(i + 1);
+        // Resume flushing in the next tick
+        Scheduler_scheduleCallback(
+          Scheduler_ImmediatePriority,
+          flushSyncCallbackQueue,
+        );
+        throw error;
+      } finally {
+        isFlushingSyncQueue = false;
       }
-      // Resume flushing in the next tick
-      Scheduler_scheduleCallback(
-        Scheduler_ImmediatePriority,
-        flushSyncCallbackQueue,
-      );
-      throw error;
-    } finally {
-      setCurrentUpdateLanePriority(previousLanePriority);
-      isFlushingSyncQueue = false;
     }
   }
 }
diff --git a/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js b/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js
index 99780f6dbaff3..18e4ba82ab36c 100644
--- a/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js
+++ b/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js
@@ -13,7 +13,10 @@ import type {ReactPriorityLevel} from './ReactInternalTypes';
 // CommonJS interop named imports.
 import * as Scheduler from 'scheduler';
 import {__interactionsRef} from 'scheduler/tracing';
-import {enableSchedulerTracing} from 'shared/ReactFeatureFlags';
+import {
+  enableSchedulerTracing,
+  decoupleUpdatePriorityFromScheduler,
+} from 'shared/ReactFeatureFlags';
 import invariant from 'shared/invariant';
 import {
   SyncLanePriority,
@@ -176,34 +179,63 @@ function flushSyncCallbackQueueImpl() {
     // Prevent re-entrancy.
     isFlushingSyncQueue = true;
     let i = 0;
-    const previousLanePriority = getCurrentUpdateLanePriority();
-    try {
-      const isSync = true;
-      const queue = syncQueue;
-      setCurrentUpdateLanePriority(SyncLanePriority);
-      runWithPriority(ImmediatePriority, () => {
-        for (; i < queue.length; i++) {
-          let callback = queue[i];
-          do {
-            callback = callback(isSync);
-          } while (callback !== null);
+    if (decoupleUpdatePriorityFromScheduler) {
+      const previousLanePriority = getCurrentUpdateLanePriority();
+      try {
+        const isSync = true;
+        const queue = syncQueue;
+        setCurrentUpdateLanePriority(SyncLanePriority);
+        runWithPriority(ImmediatePriority, () => {
+          for (; i < queue.length; i++) {
+            let callback = queue[i];
+            do {
+              callback = callback(isSync);
+            } while (callback !== null);
+          }
+        });
+        syncQueue = null;
+      } catch (error) {
+        // If something throws, leave the remaining callbacks on the queue.
+        if (syncQueue !== null) {
+          syncQueue = syncQueue.slice(i + 1);
+        }
+        // Resume flushing in the next tick
+        Scheduler_scheduleCallback(
+          Scheduler_ImmediatePriority,
+          flushSyncCallbackQueue,
+        );
+        throw error;
+      } finally {
+        setCurrentUpdateLanePriority(previousLanePriority);
+        isFlushingSyncQueue = false;
+      }
+    } else {
+      try {
+        const isSync = true;
+        const queue = syncQueue;
+        runWithPriority(ImmediatePriority, () => {
+          for (; i < queue.length; i++) {
+            let callback = queue[i];
+            do {
+              callback = callback(isSync);
+            } while (callback !== null);
+          }
+        });
+        syncQueue = null;
+      } catch (error) {
+        // If something throws, leave the remaining callbacks on the queue.
+        if (syncQueue !== null) {
+          syncQueue = syncQueue.slice(i + 1);
         }
-      });
-      syncQueue = null;
-    } catch (error) {
-      // If something throws, leave the remaining callbacks on the queue.
-      if (syncQueue !== null) {
-        syncQueue = syncQueue.slice(i + 1);
+        // Resume flushing in the next tick
+        Scheduler_scheduleCallback(
+          Scheduler_ImmediatePriority,
+          flushSyncCallbackQueue,
+        );
+        throw error;
+      } finally {
+        isFlushingSyncQueue = false;
       }
-      // Resume flushing in the next tick
-      Scheduler_scheduleCallback(
-        Scheduler_ImmediatePriority,
-        flushSyncCallbackQueue,
-      );
-      throw error;
-    } finally {
-      setCurrentUpdateLanePriority(previousLanePriority);
-      isFlushingSyncQueue = false;
     }
   }
 }