diff --git a/core/lib/Drupal/Core/Entity/EntityDefinitionUpdateManager.php b/core/lib/Drupal/Core/Entity/EntityDefinitionUpdateManager.php
index 8f75bdeebfe516e0bd8a0d80789783d80ca022e5..1db9e97564fafd5ae7f52661f2d52efb23b97b17 100644
--- a/core/lib/Drupal/Core/Entity/EntityDefinitionUpdateManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityDefinitionUpdateManager.php
@@ -18,27 +18,6 @@
 class EntityDefinitionUpdateManager implements EntityDefinitionUpdateManagerInterface {
   use StringTranslationTrait;
 
-  /**
-   * Indicates that a definition has just been created.
-   *
-   * @var int
-   */
-  const DEFINITION_CREATED = 1;
-
-  /**
-   * Indicates that a definition has changes.
-   *
-   * @var int
-   */
-  const DEFINITION_UPDATED = 2;
-
-  /**
-   * Indicates that a definition has just been deleted.
-   *
-   * @var int
-   */
-  const DEFINITION_DELETED = 3;
-
   /**
    * The entity manager service.
    *
@@ -70,6 +49,22 @@ public function getChangeSummary() {
     $summary = array();
 
     foreach ($this->getChangeList() as $entity_type_id => $change_list) {
+      // Process entity type definition changes.
+      if (!empty($change_list['entity_type'])) {
+        $entity_type = $this->entityManager->getDefinition($entity_type_id);
+        $t_args = array('%entity_type' => $entity_type->getLabel());
+
+        switch ($change_list['entity_type']) {
+          case static::DEFINITION_CREATED:
+            $summary[$entity_type_id][] = $this->t('Create the %entity_type entity type.', $t_args);
+            break;
+
+          case static::DEFINITION_UPDATED:
+            $summary[$entity_type_id][] = $this->t('Update the %entity_type entity type.', $t_args);
+            break;
+        }
+      }
+
       // Process field storage definition changes.
       if (!empty($change_list['field_storage_definitions'])) {
         $storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
@@ -91,11 +86,6 @@ public function getChangeSummary() {
           }
         }
       }
-      // Process entity type definition changes.
-      if (!empty($change_list['entity_type']) && $change_list['entity_type'] == static::DEFINITION_UPDATED) {
-        $entity_type = $this->entityManager->getDefinition($entity_type_id);
-        $summary[$entity_type_id][] = $this->t('Update the %entity_type entity type.', array('%entity_type' => $entity_type->getLabel()));
-      }
     }
 
     return $summary;
@@ -110,10 +100,19 @@ public function applyUpdates() {
       // this is necessary when you change an entity type from non-revisionable
       // to revisionable and at the same time add revisionable fields to the
       // entity type.
-      if (!empty($change_list['entity_type']) && $change_list['entity_type'] == static::DEFINITION_UPDATED) {
+      if (!empty($change_list['entity_type'])) {
         $entity_type = $this->entityManager->getDefinition($entity_type_id);
-        $original = $this->entityManager->getLastInstalledDefinition($entity_type_id);
-        $this->entityManager->onEntityTypeUpdate($entity_type, $original);
+
+        switch ($change_list['entity_type']) {
+          case static::DEFINITION_CREATED:
+            $this->entityManager->onEntityTypeCreate($entity_type);
+            break;
+
+          case static::DEFINITION_UPDATED:
+            $original = $this->entityManager->getLastInstalledDefinition($entity_type_id);
+            $this->entityManager->onEntityTypeUpdate($entity_type, $original);
+            break;
+        }
       }
 
       // Process field storage definition changes.
@@ -160,54 +159,55 @@ protected function getChangeList() {
     foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) {
       $original = $this->entityManager->getLastInstalledDefinition($entity_type_id);
 
-      // Only manage changes to already installed entity types. Entity type
-      // installation is handled elsewhere (e.g.,
-      // \Drupal\Core\Extension\ModuleHandler::install()).
-      if (!$original) {
-        continue;
-      }
-
       // @todo Support non-storage-schema-changing definition updates too:
       //   https://www.drupal.org/node/2336895.
-      if ($this->requiresEntityStorageSchemaChanges($entity_type, $original)) {
-        $change_list[$entity_type_id]['entity_type'] = static::DEFINITION_UPDATED;
+      if (!$original) {
+        $change_list[$entity_type_id]['entity_type'] = static::DEFINITION_CREATED;
       }
+      else {
+        if ($this->requiresEntityStorageSchemaChanges($entity_type, $original)) {
+          $change_list[$entity_type_id]['entity_type'] = static::DEFINITION_UPDATED;
+        }
 
-      if ($this->entityManager->getStorage($entity_type_id) instanceof DynamicallyFieldableEntityStorageInterface) {
-        $field_changes = array();
-        $storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
-        $original_storage_definitions = $this->entityManager->getLastInstalledFieldStorageDefinitions($entity_type_id);
+        if ($this->entityManager->getStorage($entity_type_id) instanceof DynamicallyFieldableEntityStorageInterface) {
+          $field_changes = array();
+          $storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
+          $original_storage_definitions = $this->entityManager->getLastInstalledFieldStorageDefinitions($entity_type_id);
 
-        // Detect created field storage definitions.
-        foreach (array_diff_key($storage_definitions, $original_storage_definitions) as $field_name => $storage_definition) {
-          $field_changes[$field_name] = static::DEFINITION_CREATED;
-        }
+          // Detect created field storage definitions.
+          foreach (array_diff_key($storage_definitions, $original_storage_definitions) as $field_name => $storage_definition) {
+            $field_changes[$field_name] = static::DEFINITION_CREATED;
+          }
 
-        // Detect deleted field storage definitions.
-        foreach (array_diff_key($original_storage_definitions, $storage_definitions) as $field_name => $original_storage_definition) {
-          $field_changes[$field_name] = static::DEFINITION_DELETED;
-        }
+          // Detect deleted field storage definitions.
+          foreach (array_diff_key($original_storage_definitions, $storage_definitions) as $field_name => $original_storage_definition) {
+            $field_changes[$field_name] = static::DEFINITION_DELETED;
+          }
 
-        // Detect updated field storage definitions.
-        foreach (array_intersect_key($storage_definitions, $original_storage_definitions) as $field_name => $storage_definition) {
-          // @todo Support non-storage-schema-changing definition updates too:
-          //   https://www.drupal.org/node/2336895. So long as we're checking
-          //   based on schema change requirements rather than definition
-          //   equality, skip the check if the entity type itself needs to be
-          //   updated, since that can affect the schema of all fields, so we
-          //   want to process that update first without reporting false
-          //   positives here.
-          if (!isset($change_list[$entity_type_id]['entity_type']) && $this->requiresFieldStorageSchemaChanges($storage_definition, $original_storage_definitions[$field_name])) {
-            $field_changes[$field_name] = static::DEFINITION_UPDATED;
+          // Detect updated field storage definitions.
+          foreach (array_intersect_key($storage_definitions, $original_storage_definitions) as $field_name => $storage_definition) {
+            // @todo Support non-storage-schema-changing definition updates too:
+            //   https://www.drupal.org/node/2336895. So long as we're checking
+            //   based on schema change requirements rather than definition
+            //   equality, skip the check if the entity type itself needs to be
+            //   updated, since that can affect the schema of all fields, so we
+            //   want to process that update first without reporting false
+            //   positives here.
+            if (!isset($change_list[$entity_type_id]['entity_type']) && $this->requiresFieldStorageSchemaChanges($storage_definition, $original_storage_definitions[$field_name])) {
+              $field_changes[$field_name] = static::DEFINITION_UPDATED;
+            }
           }
-        }
 
-        if ($field_changes) {
-          $change_list[$entity_type_id]['field_storage_definitions'] = $field_changes;
+          if ($field_changes) {
+            $change_list[$entity_type_id]['field_storage_definitions'] = $field_changes;
+          }
         }
       }
     }
 
+    // @todo Support deleting entity definitions when we support base field
+    //   purging. See https://www.drupal.org/node/2282119.
+
     return array_filter($change_list);
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityDefinitionUpdateManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityDefinitionUpdateManagerInterface.php
index c6ead5b9acc8979993dfb40e80c45d13f5e6c9b5..25bbdade1e8e7750cde31cd92a4a7d7151267011 100644
--- a/core/lib/Drupal/Core/Entity/EntityDefinitionUpdateManagerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityDefinitionUpdateManagerInterface.php
@@ -34,6 +34,27 @@
  */
 interface EntityDefinitionUpdateManagerInterface {
 
+  /**
+   * Indicates that a definition has just been created.
+   *
+   * @var int
+   */
+  const DEFINITION_CREATED = 1;
+
+  /**
+   * Indicates that a definition has changes.
+   *
+   * @var int
+   */
+  const DEFINITION_UPDATED = 2;
+
+  /**
+   * Indicates that a definition has just been deleted.
+   *
+   * @var int
+   */
+  const DEFINITION_DELETED = 3;
+
   /**
    * Checks if there are any definition updates that need to be applied.
    *
diff --git a/core/modules/locale/src/Tests/LocaleTranslatedSchemaDefinitionTest.php b/core/modules/locale/src/Tests/LocaleTranslatedSchemaDefinitionTest.php
index 73a9f25c1d644783d091ca6e29ae6af5e2e5e0d3..f94db02971030bebb53ec4f020470e6b1d6e8f95 100644
--- a/core/modules/locale/src/Tests/LocaleTranslatedSchemaDefinitionTest.php
+++ b/core/modules/locale/src/Tests/LocaleTranslatedSchemaDefinitionTest.php
@@ -31,6 +31,8 @@ protected function setUp() {
     parent::setUp();
     ConfigurableLanguage::createFromLangcode('fr')->save();
     $this->config('system.site')->set('langcode', 'fr')->save();
+    // Make sure new entity type definitions are processed.
+    \Drupal::service('entity.definition_update_manager')->applyUpdates();
     // Clear all caches so that the base field definition, its cache in the
     // entity manager, the t() cache, etc. are all cleared.
     drupal_flush_all_caches();
diff --git a/core/modules/system/src/Tests/Entity/EntityDefinitionTestTrait.php b/core/modules/system/src/Tests/Entity/EntityDefinitionTestTrait.php
index ffc5a2e8180551314f8d3a9379942dcc4cd94565..353dd4d8ca39394d11ad73b6c6567762cf15aa77 100644
--- a/core/modules/system/src/Tests/Entity/EntityDefinitionTestTrait.php
+++ b/core/modules/system/src/Tests/Entity/EntityDefinitionTestTrait.php
@@ -15,6 +15,15 @@
  */
 trait EntityDefinitionTestTrait {
 
+  /**
+   * Enables a new entity type definition.
+   */
+  protected function enableNewEntityType() {
+    $this->state->set('entity_test_new', TRUE);
+    $this->entityManager->clearCachedDefinitions();
+    $this->entityDefinitionUpdateManager->applyUpdates();
+  }
+
   /**
    * Resets the entity type definition.
    */
diff --git a/core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php b/core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php
index 33c1a05c821d1b588e461e78e779048b25380403..05d2a06f88f937c993c76d8dd44dee8826a5f688 100644
--- a/core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php
@@ -54,6 +54,26 @@ protected function setUp() {
     }
   }
 
+  /**
+   * Tests that new entity type definitions are correctly handled.
+   */
+  public function testNewEntityType() {
+    $entity_type_id = 'entity_test_new';
+    $schema = $this->database->schema();
+
+    // Check that the "entity_test_new" is not defined.
+    $entity_types = $this->entityManager->getDefinitions();
+    $this->assertFalse(isset($entity_types[$entity_type_id]), 'The "entity_test_new" entity type does not exist.');
+    $this->assertFalse($schema->tableExists($entity_type_id), 'Schema for the "entity_test_new" entity type does not exist.');
+
+    // Check that the "entity_test_new" is now defined and the related schema
+    // has been created.
+    $this->enableNewEntityType();
+    $entity_types = $this->entityManager->getDefinitions();
+    $this->assertTrue(isset($entity_types[$entity_type_id]), 'The "entity_test_new" entity type exists.');
+    $this->assertTrue($schema->tableExists($entity_type_id), 'Schema for the "entity_test_new" entity type has been created.');
+  }
+
   /**
    * Tests when no definition update is needed.
    */
diff --git a/core/modules/system/src/Tests/Update/UpdateScriptTest.php b/core/modules/system/src/Tests/Update/UpdateScriptTest.php
index 5b09674e356a873a3bbee3200dbf23039a196bb7..2da975fb5c3ee19a015aa223526ea8edd17abac9 100644
--- a/core/modules/system/src/Tests/Update/UpdateScriptTest.php
+++ b/core/modules/system/src/Tests/Update/UpdateScriptTest.php
@@ -32,6 +32,8 @@ protected function setUp() {
     parent::setUp();
     $this->update_url = $GLOBALS['base_url'] . '/update.php';
     $this->update_user = $this->drupalCreateUser(array('administer software updates', 'access site in maintenance mode'));
+    // Make sure updates for new entity type definitions are processed.
+    \Drupal::service('entity.definition_update_manager')->applyUpdates();
   }
 
   /**
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index 9317d3c7d394e789cc750cf280da8b979303d76f..64418c7291e55b2f9692f954d1f69ab6262cf4aa 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -74,10 +74,12 @@ function entity_test_entity_types($filter = NULL) {
  * Implements hook_entity_type_alter().
  */
 function entity_test_entity_type_alter(array &$entity_types) {
+  $state = \Drupal::state();
+
   /** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
   foreach (entity_test_entity_types() as $entity_type) {
     // Optionally specify a translation handler for testing translations.
-    if (\Drupal::state()->get('entity_test.translation')) {
+    if ($state->get('entity_test.translation')) {
       $translation = $entity_types[$entity_type]->get('translation');
       $translation[$entity_type] = TRUE;
       $entity_types[$entity_type]->set('translation', $translation);
@@ -85,7 +87,12 @@ function entity_test_entity_type_alter(array &$entity_types) {
   }
 
   // Allow entity_test_update tests to override the entity type definition.
-  $entity_types['entity_test_update'] = \Drupal::state()->get('entity_test_update.entity_type', $entity_types['entity_test_update']);
+  $entity_types['entity_test_update'] = $state->get('entity_test_update.entity_type', $entity_types['entity_test_update']);
+
+  // Enable the entity_test_new only when needed.
+  if (!$state->get('entity_test_new')) {
+    unset($entity_types['entity_test_new']);
+  }
 }
 
 /**
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNew.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNew.php
new file mode 100644
index 0000000000000000000000000000000000000000..9adb52d046434eb1b275d03642e3315e3d51eb40
--- /dev/null
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNew.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity_test\Entity\EntityTestNew.
+ */
+
+namespace Drupal\entity_test\Entity;
+
+/**
+ * Defines the test entity class for testing definition addition.
+ *
+ * This entity type is initially not defined. It is enabled when needed to test
+ * the related updates.
+ *
+ * @ContentEntityType(
+ *   id = "entity_test_new",
+ *   label = @Translation("New test entity"),
+ *   base_table = "entity_test_new",
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "uuid" = "uuid",
+ *     "bundle" = "type",
+ *     "label" = "name",
+ *     "langcode" = "langcode",
+ *   }
+ * )
+ */
+class EntityTestNew extends EntityTest {
+}