diff --git src/wp-includes/customize/class-wp-customize-selective-refresh.php src/wp-includes/customize/class-wp-customize-selective-refresh.php
index 0b5c446131..2f49608963 100644
--- src/wp-includes/customize/class-wp-customize-selective-refresh.php
+++ src/wp-includes/customize/class-wp-customize-selective-refresh.php
@@ -65,6 +65,8 @@ final class WP_Customize_Selective_Refresh {
 		require_once( ABSPATH . WPINC . '/customize/class-wp-customize-partial.php' );
 
 		add_action( 'customize_preview_init', array( $this, 'init_preview' ) );
+		add_action( 'customize_preview_init', [ $this, 'check_transport_of_settings_with_partials' ] );
+		add_action( 'customize_controls_init', [ $this, 'check_transport_of_settings_with_partials' ] );
 	}
 
 	/**
@@ -72,7 +74,7 @@ final class WP_Customize_Selective_Refresh {
 	 *
 	 * @since 4.5.0
 	 *
-	 * @return array Partials.
+	 * @return WP_Customize_Partial[] Partials.
 	 */
 	public function partials() {
 		return $this->partials;
@@ -163,6 +165,49 @@ final class WP_Customize_Selective_Refresh {
 		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_preview_scripts' ) );
 	}
 
+	/**
+	 * Ensure that settings associated with partials use the 'postMessage' transport.
+	 */
+	public function check_transport_of_settings_with_partials() {
+		foreach ( $this->partials() as $partial ) {
+			/*
+			 * It's possible to register a partial for a setting while intending
+			 * to use the partial in only certain circumstances. Before
+			 * enforcing the 'postMessage' transport for such settings, check
+			 * that the partial is configured to request a full refresh of the
+			 * preview if the selective refresh fails because the partial isn't
+			 * actually used in the preview.
+			 */
+			if ( ! $partial->fallback_refresh ) {
+				continue;
+			}
+
+			foreach ( $partial->settings as $setting_id ) {
+				$setting = $this->manager->get_setting( $setting_id );
+
+				if ( $setting instanceof WP_Customize_Setting ) {
+					// Change only the 'refresh' transport, not custom transports.
+					if ( 'refresh' !== $setting->transport ) {
+						continue;
+					}
+
+					/*
+					 * If the partial is unsupported, don't change any settings.
+					 *
+					 * Save this check until the end to avoid unnecessarily
+					 * re-checking the capabilities for partials and all their
+					 * settings when the settings already use 'postMessage'.
+					 */
+					if ( ! $partial->check_capabilities() ) {
+						continue 2;
+					}
+
+					$setting->transport = 'postMessage';
+				}
+			}
+		}
+	}
+
 	/**
 	 * Enqueues preview scripts.
 	 *
diff --git tests/phpunit/tests/customize/selective-refresh.php tests/phpunit/tests/customize/selective-refresh.php
index 3edeee4170..e1f2a6759f 100644
--- tests/phpunit/tests/customize/selective-refresh.php
+++ tests/phpunit/tests/customize/selective-refresh.php
@@ -116,6 +116,134 @@ class Test_WP_Customize_Selective_Refresh extends WP_UnitTestCase {
 		$this->assertEquals( 10, has_action( 'wp_enqueue_scripts', array( $this->selective_refresh, 'enqueue_preview_scripts' ) ) );
 	}
 
+	/**
+	 * Test \WP_Customize_Selective_Refresh::check_transport_of_settings_with_partials().
+	 *
+	 * @see \WP_Customize_Selective_Refresh::check_transport_of_settings_with_partials()
+	 */
+	public function test_check_transport_of_settings_with_partials() {
+		wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
+
+		// Test case with ineligible partial.
+		$this->wp_customize->add_setting(
+			'cat',
+			array(
+				'transport' => 'refresh',
+			)
+		);
+		$this->wp_customize->selective_refresh->add_partial(
+			'cat',
+			array(
+				'fallback_refresh' => false,
+			)
+		);
+
+		// Test case with ineligible setting transport.
+		$this->wp_customize->add_setting(
+			'elephant',
+			array(
+				'transport' => 'bicycle',
+			)
+		);
+		$this->wp_customize->selective_refresh->add_partial( 'elephant' );
+
+		// Test case with ineligible partial capability.
+		$this->wp_customize->add_setting(
+			'horse',
+			array(
+				'transport' => 'refresh',
+			)
+		);
+		$this->wp_customize->selective_refresh->add_partial(
+			'horse',
+			array(
+				'capability' => 'do_not_allow',
+			)
+		);
+
+		// Test case with ineligible setting capability.
+		$this->wp_customize->add_setting(
+			'mouse',
+			array(
+				'capability' => 'do_not_allow',
+			)
+		);
+		$this->wp_customize->selective_refresh->add_partial( 'mouse' );
+
+		// Test case with one ineligible setting.
+		$this->wp_customize->add_setting(
+			'bat',
+			array(
+				'transport' => 'refresh',
+			)
+		);
+		$this->wp_customize->add_setting(
+			'tiger',
+			array(
+				'transport'  => 'refresh',
+				'capability' => 'do_not_allow',
+			)
+		);
+		$this->wp_customize->selective_refresh->add_partial(
+			'circus',
+			array(
+				'settings' => array( 'bat', 'tiger' ),
+			)
+		);
+
+		// Test case with one eligible setting.
+		$this->wp_customize->add_setting(
+			'dog',
+			array(
+				'transport' => 'refresh',
+			)
+		);
+		$this->wp_customize->selective_refresh->add_partial( 'dog' );
+
+		// Test case with many eligible settings.
+		$this->wp_customize->add_setting(
+			'spider',
+			array(
+				'transport' => 'refresh',
+			)
+		);
+		$this->wp_customize->add_setting(
+			'hawk',
+			array(
+				'transport' => 'refresh',
+			)
+		);
+		$this->wp_customize->selective_refresh->add_partial(
+			'zoo',
+			array(
+				'settings' => array( 'spider', 'hawk' ),
+			)
+		);
+
+		$this->wp_customize->selective_refresh->check_transport_of_settings_with_partials();
+
+		// This setting should not have been changed because it doesn't support 'fallback_refresh'.
+		$this->assertSame( 'refresh', $this->wp_customize->get_setting( 'cat' )->transport );
+
+		// This setting should not have been changed because it uses a custom transport.
+		$this->assertSame( 'bicycle', $this->wp_customize->get_setting( 'elephant' )->transport );
+
+		// This setting should not have been changed because of the partial's capability.
+		$this->assertSame( 'refresh', $this->wp_customize->get_setting( 'horse' )->transport );
+
+		// This setting should not have been changed because of the setting's capability.
+		$this->assertSame( 'refresh', $this->wp_customize->get_setting( 'mouse' )->transport );
+
+		// Neither of these settings from the same partial should have been changed because of one of the settings' capability.
+		$this->assertSame( 'refresh', $this->wp_customize->get_setting( 'bat' )->transport );
+		$this->assertSame( 'refresh', $this->wp_customize->get_setting( 'tiger' )->transport );
+
+		// These settings should have been updated to use 'postMessage'.
+		$this->assertSame( 'postMessage', $this->wp_customize->get_setting( 'dog' )->transport );
+		$this->assertSame( 'postMessage', $this->wp_customize->get_setting( 'spider' )->transport );
+		$this->assertSame( 'postMessage', $this->wp_customize->get_setting( 'hawk' )->transport );
+	}
+
 	/**
 	 * Test WP_Customize_Selective_Refresh::enqueue_preview_scripts().
 	 *
