diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
index 033cb5f178186830dad3d8e15c8bbe3d1112323c..5569dd09893dc69be9d4dba5c239157eab5a055e 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
@@ -256,8 +256,8 @@ public function save(EntityInterface $entity) {
     // @see \Drupal\Core\Config\Entity\ConfigEntityStorage::MAX_ID_LENGTH
     // @todo Consider moving this to a protected method on the parent class, and
     //   abstracting it for all entity types.
-    if (strlen($entity->get($this->idKey)) > self::MAX_ID_LENGTH) {
-      throw new ConfigEntityIdLengthException("Configuration entity ID {$entity->get($this->idKey)} exceeds maximum allowed length of " . self::MAX_ID_LENGTH . " characters.");
+    if (strlen($entity->get($this->idKey)) > static::MAX_ID_LENGTH) {
+      throw new ConfigEntityIdLengthException("Configuration entity ID {$entity->get($this->idKey)} exceeds maximum allowed length of " . static::MAX_ID_LENGTH . " characters.");
     }
 
     return parent::save($entity);
diff --git a/core/modules/menu_ui/menu_ui.module b/core/modules/menu_ui/menu_ui.module
index d804ae6ceaa17d31ffef394673fc72482232ce6f..17320f500b25ce196be0f5e4cbeb80011b9574d0 100644
--- a/core/modules/menu_ui/menu_ui.module
+++ b/core/modules/menu_ui/menu_ui.module
@@ -25,10 +25,10 @@
  * Maximum length of menu name as entered by the user.
  *
  * @deprecated in drupal:8.3.0 and is removed from drupal:9.0.0. Use
- *   \Drupal\Core\Config\Entity\ConfigEntityStorage::MAX_ID_LENGTH because the
- *   menu name is a configuration entity ID.
+ *   \Drupal\system\MenuStorage::MAX_ID_LENGTH instead.
  *
  * @see https://www.drupal.org/node/2831620
+ * @see \Drupal\system\MenuStorage::MAX_ID_LENGTH
  */
 const MENU_MAX_MENU_NAME_LENGTH_UI = 27;
 
diff --git a/core/modules/menu_ui/src/MenuForm.php b/core/modules/menu_ui/src/MenuForm.php
index ccedad3133eb2b2b693c68e1d9388dad13a14e84..5a2044e8a07d4c239a354c8b70add2f6d419cd8e 100644
--- a/core/modules/menu_ui/src/MenuForm.php
+++ b/core/modules/menu_ui/src/MenuForm.php
@@ -17,6 +17,7 @@
 use Drupal\Core\Utility\LinkGeneratorInterface;
 use Drupal\menu_link_content\MenuLinkContentStorageInterface;
 use Drupal\menu_link_content\Plugin\Menu\MenuLinkContent;
+use Drupal\system\MenuStorage;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -112,7 +113,7 @@ public function form(array $form, FormStateInterface $form_state) {
       '#type' => 'machine_name',
       '#title' => $this->t('Menu name'),
       '#default_value' => $menu->id(),
-      '#maxlength' => MENU_MAX_MENU_NAME_LENGTH_UI,
+      '#maxlength' => MenuStorage::MAX_ID_LENGTH,
       '#description' => $this->t('A unique name to construct the URL for the menu. It must only contain lowercase letters, numbers and hyphens.'),
       '#machine_name' => [
         'exists' => [$this, 'menuNameExists'],
diff --git a/core/modules/menu_ui/tests/src/Functional/MenuUiTest.php b/core/modules/menu_ui/tests/src/Functional/MenuUiTest.php
index d04075d004b6f4886ea7adb6c2171317d28e65a9..63626bbf43d051cfaeba643776f203af98571ce7 100644
--- a/core/modules/menu_ui/tests/src/Functional/MenuUiTest.php
+++ b/core/modules/menu_ui/tests/src/Functional/MenuUiTest.php
@@ -10,6 +10,7 @@
 use Drupal\system\Entity\Menu;
 use Drupal\node\Entity\Node;
 use Drupal\node\NodeInterface;
+use Drupal\system\MenuStorage;
 use Drupal\Tests\BrowserTestBase;
 use Drupal\Tests\menu_ui\Traits\MenuUiTrait;
 
@@ -167,7 +168,7 @@ public function testMenu() {
    */
   public function addCustomMenuCRUD() {
     // Add a new custom menu.
-    $menu_name = substr(hash('sha256', $this->randomMachineName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI);
+    $menu_name = strtolower($this->randomMachineName(MenuStorage::MAX_ID_LENGTH));
     $label = $this->randomMachineName(16);
 
     $menu = Menu::create([
@@ -198,7 +199,7 @@ public function addCustomMenuCRUD() {
   public function addCustomMenu() {
     // Try adding a menu using a menu_name that is too long.
     $this->drupalGet('admin/structure/menu/add');
-    $menu_name = substr(hash('sha256', $this->randomMachineName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI + 1);
+    $menu_name = strtolower($this->randomMachineName(MenuStorage::MAX_ID_LENGTH + 1));
     $label = $this->randomMachineName(16);
     $edit = [
       'id' => $menu_name,
@@ -211,19 +212,19 @@ public function addCustomMenu() {
     // message.
     $this->assertRaw(t('@name cannot be longer than %max characters but is currently %length characters long.', [
       '@name' => t('Menu name'),
-      '%max' => MENU_MAX_MENU_NAME_LENGTH_UI,
+      '%max' => MenuStorage::MAX_ID_LENGTH,
       '%length' => mb_strlen($menu_name),
     ]));
 
     // Change the menu_name so it no longer exceeds the maximum length.
-    $menu_name = substr(hash('sha256', $this->randomMachineName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI);
+    $menu_name = strtolower($this->randomMachineName(MenuStorage::MAX_ID_LENGTH));
     $edit['id'] = $menu_name;
     $this->drupalPostForm('admin/structure/menu/add', $edit, t('Save'));
 
     // Verify that no validation error is given for menu_name length.
     $this->assertNoRaw(t('@name cannot be longer than %max characters but is currently %length characters long.', [
       '@name' => t('Menu name'),
-      '%max' => MENU_MAX_MENU_NAME_LENGTH_UI,
+      '%max' => MenuStorage::MAX_ID_LENGTH,
       '%length' => mb_strlen($menu_name),
     ]));
     // Verify that the confirmation message is displayed.
diff --git a/core/modules/menu_ui/tests/src/FunctionalJavascript/MenuUiJavascriptTest.php b/core/modules/menu_ui/tests/src/FunctionalJavascript/MenuUiJavascriptTest.php
index fea04e60bddf0503d80adeef22d955ccf9e1abe5..f9f9e8c406ea6ca0f70cb5e13fa22d912a352bf9 100644
--- a/core/modules/menu_ui/tests/src/FunctionalJavascript/MenuUiJavascriptTest.php
+++ b/core/modules/menu_ui/tests/src/FunctionalJavascript/MenuUiJavascriptTest.php
@@ -4,6 +4,7 @@
 
 use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
 use Drupal\system\Entity\Menu;
+use Drupal\system\MenuStorage;
 use Drupal\Tests\contextual\FunctionalJavascript\ContextualLinkClickTrait;
 use Drupal\Tests\menu_ui\Traits\MenuUiTrait;
 
@@ -74,7 +75,7 @@ public function testBlockContextualLinks() {
   protected function addCustomMenu() {
     // Try adding a menu using a menu_name that is too long.
     $label = $this->randomMachineName(16);
-    $menu_id = strtolower($this->randomMachineName(MENU_MAX_MENU_NAME_LENGTH_UI + 1));
+    $menu_id = strtolower($this->randomMachineName(MenuStorage::MAX_ID_LENGTH + 1));
 
     $this->drupalGet('admin/structure/menu/add');
     $page = $this->getSession()->getPage();
@@ -88,7 +89,7 @@ protected function addCustomMenu() {
     $page->fillField('Menu name', $menu_id);
     $page->pressButton('Save');
     // Check that the menu was saved with the ID truncated to the max length.
-    $menu = Menu::load(substr($menu_id, 0, MENU_MAX_MENU_NAME_LENGTH_UI));
+    $menu = Menu::load(substr($menu_id, 0, MenuStorage::MAX_ID_LENGTH));
     $this->assertEquals($label, $menu->label());
 
     // Check that the menu was added.
diff --git a/core/modules/system/src/Entity/Menu.php b/core/modules/system/src/Entity/Menu.php
index 14830099e0a2562f5f55408e0d04f8de9b07c456..546aa34a86e93032ed1945a66c5a8b37a7f3764f 100644
--- a/core/modules/system/src/Entity/Menu.php
+++ b/core/modules/system/src/Entity/Menu.php
@@ -20,7 +20,8 @@
  *     plural = "@count menus",
  *   ),
  *   handlers = {
- *     "access" = "Drupal\system\MenuAccessControlHandler"
+ *     "access" = "Drupal\system\MenuAccessControlHandler",
+ *     "storage" = "Drupal\system\MenuStorage",
  *   },
  *   admin_permission = "administer menu",
  *   entity_keys = {
diff --git a/core/modules/system/src/MenuStorage.php b/core/modules/system/src/MenuStorage.php
new file mode 100644
index 0000000000000000000000000000000000000000..0d9d9560f6a83da46291c0467a30c61358565f8b
--- /dev/null
+++ b/core/modules/system/src/MenuStorage.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Drupal\system;
+
+use Drupal\Core\Config\Entity\ConfigEntityStorage;
+
+/**
+ * Defines the storage class for menu configuration entities.
+ */
+class MenuStorage extends ConfigEntityStorage {
+
+  /**
+   * Menu names have a maximum length of 32.
+   *
+   * This is based on:
+   * - menu_tree table schema definition,
+   * - \Drupal\Core\Config\Entity\ConfigEntityStorage::MAX_ID_LENGTH
+   * - menu_name base field on the Menu Link content entity.
+   *
+   * @see \Drupal\Core\Menu\MenuTreeStorage::schemaDefinition()
+   * @see \Drupal\menu_link_content\Entity\MenuLinkContent::baseFieldDefinitions()
+   */
+  const MAX_ID_LENGTH = 32;
+
+}
diff --git a/core/modules/system/tests/src/Kernel/Menu/MenuStorageTest.php b/core/modules/system/tests/src/Kernel/Menu/MenuStorageTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..bec077f40acfe6fece66edf7c912b3ae8a41ed29
--- /dev/null
+++ b/core/modules/system/tests/src/Kernel/Menu/MenuStorageTest.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Drupal\Tests\system\Kernel\Menu;
+
+use Drupal\Core\Config\Entity\Exception\ConfigEntityIdLengthException;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\system\Entity\Menu;
+use Drupal\system\MenuStorage;
+
+/**
+ * Tests MenuStorage.
+ *
+ * @group Menu
+ *
+ * @see \Drupal\system\MenuStorage
+ */
+class MenuStorageTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['system'];
+
+  /**
+   * Tests MenuStorage::MAX_ID_LENGTH is enforced.
+   */
+  public function testMaxIdLengthException() {
+    $id = $this->randomMachineName(MenuStorage::MAX_ID_LENGTH + 1);
+    $this->expectException(ConfigEntityIdLengthException::class);
+    $this->expectExceptionMessage(
+      sprintf('Configuration entity ID %s exceeds maximum allowed length of %s characters.', $id, MenuStorage::MAX_ID_LENGTH)
+    );
+    Menu::create(['id' => $id])->save();
+  }
+
+}