diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index 700ad04445f779fd2e6bcdd5d564dbacf2d3ea37..1d66dc3a0f102041aaca34b9700d6044a25618f3 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -352,6 +352,7 @@ private function doInstall(array $module_list, array $installed_modules, bool $s
     // @todo should this be in the loop?
     \Drupal::getContainer()->get('plugin.cache_clearer')->clearCachedDefinitions();
 
+    $entity_type_providers_to_install = $module_list;
     foreach ($module_list as $module) {
       // Set the schema version to the number of the last update provided by
       // the module, or the minimum core schema version.
@@ -361,6 +362,10 @@ private function doInstall(array $module_list, array $installed_modules, bool $s
         $version = max(max($versions), $version);
       }
 
+      // Remove the module from the list of possible entity type providers to
+      // install.
+      array_shift($entity_type_providers_to_install);
+
       // Notify interested components that this module's entity types and
       // field storage definitions are new. For example, a SQL-based storage
       // handler can use this as an opportunity to create the necessary
@@ -381,10 +386,10 @@ private function doInstall(array $module_list, array $installed_modules, bool $s
             $update_manager->installEntityType($entity_type);
           }
         }
-        elseif ($is_fieldable_entity_type) {
+        elseif ($is_fieldable_entity_type && !in_array($entity_type->getProvider(), $entity_type_providers_to_install, TRUE)) {
           // The module being installed may be adding new fields to existing
           // entity types. Field definitions for any entity type defined by
-          // the module are handled in the if branch.
+          // modules being installed are handled in the if branch.
           foreach ($entity_field_manager->getFieldStorageDefinitions($entity_type->id()) as $storage_definition) {
             if ($storage_definition->getProvider() == $module) {
               // If the module being installed is also defining a storage key
diff --git a/core/modules/system/tests/modules/field_storage_entity_type_dependency_test/field_storage_entity_type_dependency_test.info.yml b/core/modules/system/tests/modules/field_storage_entity_type_dependency_test/field_storage_entity_type_dependency_test.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c0c6defce6833945ae0bfee97acf409741bfe865
--- /dev/null
+++ b/core/modules/system/tests/modules/field_storage_entity_type_dependency_test/field_storage_entity_type_dependency_test.info.yml
@@ -0,0 +1,5 @@
+name: 'Field storage entity type dependency test'
+type: module
+description: 'Introduces a module dependency where entity types need to be installed before field storage definitions.'
+package: Testing
+version: VERSION
diff --git a/core/modules/system/tests/modules/field_storage_entity_type_dependency_test/src/Hook/FieldStorageEntityTypeDependencyTestHook.php b/core/modules/system/tests/modules/field_storage_entity_type_dependency_test/src/Hook/FieldStorageEntityTypeDependencyTestHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..ff7ab50de67a0b931f761c60e01425502fd2e68c
--- /dev/null
+++ b/core/modules/system/tests/modules/field_storage_entity_type_dependency_test/src/Hook/FieldStorageEntityTypeDependencyTestHook.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\field_storage_entity_type_dependency_test\Hook;
+
+use Drupal\Core\Extension\Extension;
+use Drupal\Core\Hook\Attribute\Hook;
+
+/**
+ * Hook implementations.
+ */
+class FieldStorageEntityTypeDependencyTestHook {
+
+  /**
+   * Implements hook_system_info_alter().
+   */
+  #[Hook('system_info_alter')]
+  public function systemInfoAlter(array &$info, Extension $file, string $type): void {
+    if ($file->getName() === 'taxonomy') {
+      $info['dependencies'][] = 'drupal:workspaces';
+    }
+  }
+
+}
diff --git a/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php b/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php
index f2dddc48770d3a60ab86095bda8ce2f2a7509ed3..22ac70ddbe84459f28ddd297ac4c1af0324c801b 100644
--- a/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php
@@ -5,11 +5,15 @@
 namespace Drupal\KernelTests\Core\Extension;
 
 use Drupal\Core\Database\Database;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\Extension\MissingDependencyException;
 use Drupal\Core\Extension\Exception\ObsoleteExtensionException;
 use Drupal\Core\Extension\ModuleInstaller;
 use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
+use Drupal\Core\Logger\RfcLoggerTrait;
+use Drupal\Core\Logger\RfcLogLevel;
 use Drupal\KernelTests\KernelTestBase;
+use Psr\Log\LoggerInterface;
 use Symfony\Component\Routing\Exception\RouteNotFoundException;
 
 /**
@@ -19,7 +23,9 @@
  *
  * @group Extension
  */
-class ModuleInstallerTest extends KernelTestBase {
+class ModuleInstallerTest extends KernelTestBase implements LoggerInterface {
+
+  use RfcLoggerTrait;
 
   /**
    * Tests that routes are rebuilt during install and uninstall of modules.
@@ -239,4 +245,50 @@ public function testUninstallValidatorsBC(): void {
     $module_installer->addUninstallValidator($this->createMock(ModuleUninstallValidatorInterface::class));
   }
 
+  /**
+   * Tests field storage definitions are installed only if entity types exist.
+   */
+  public function testFieldStorageEntityTypeDependencies(): void {
+    $profile = 'minimal';
+    $this->setInstallProfile($profile);
+    // Install a module that will make workspaces a dependency of taxonomy.
+    \Drupal::service('module_installer')->install(['field_storage_entity_type_dependency_test']);
+    // Installing taxonomy will install workspaces first. During installation of
+    // workspaces, the storage for 'workspace' field should not be attempted
+    // before the taxonomy term entity storage has been created, so there
+    // should not be a EntityStorageException logged.
+    \Drupal::service('module_installer')->install(['taxonomy']);
+    $this->assertTrue(\Drupal::moduleHandler()->moduleExists('workspaces'));
+    $this->assertTrue(\Drupal::moduleHandler()->moduleExists('taxonomy'));
+    $this->assertArrayHasKey('workspace', \Drupal::service('entity_field.manager')->getBaseFieldDefinitions('taxonomy_term'));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function register(ContainerBuilder $container): void {
+    parent::register($container);
+
+    $container
+      ->register(__CLASS__, __CLASS__)
+      ->setSynthetic(TRUE)
+      ->addTag('logger');
+    $container->set(__CLASS__, $this);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function log($level, \Stringable|string $message, array $context = []): void {
+    if ($level > RfcLogLevel::ERROR) {
+      return;
+    }
+
+    // Fails the test if an error or more severe message is logged.
+    $message = (string) $message;
+    $placeholders = \Drupal::service('logger.log_message_parser')->parseMessagePlaceholders($message, $context);
+    $message = empty($placeholders) ? $message : strtr($message, $placeholders);
+    $this->fail($message);
+  }
+
 }