How can i add a property(uuid) to existing custom entity base_table? I want to add uuid property to existing custom entity extending ContentEntityBase.
I've tried to a add the uuid entity key and installed field storage definition by:
function my_module_post_update_adduuid() {
  \Drupal::entityTypeManager()-&gt;clearCachedDefinitions();
  $definition_update_manager = \Drupal::entityDefinitionUpdateManager();

  /** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $last_installed_schema_repository */
  $field_storage_definition = BaseFieldDefinition::create('uuid')
    -&gt;setLabel(new TranslatableMarkup('UUID'))
    -&gt;setReadOnly(TRUE);

  $definition_update_manager-&gt;installFieldStorageDefinition('uuid', 'custom_entity_id', 'custom_entity_id', $field_storage_definition);
}

The &quot;problem&quot; is that for custom entity with data_table defined the property is added to the data_table and not to the base_table as expected. If the custom entity doesn't have data table defined the uuid property is written properly in base_table.
Everything seems to work even though the uuid property is defined in data_table but the schema is inconsistent compared to clean install with the uuid key present from the beginning.
Found a workaround for this:
Step 1: Add uuid to entity keys in annotation.
Step 2: Add custom storage handler in annotation.
Step 3: Create the custom storage handler class extending SqlContentEntityStorage with getCustomTableMapping overridden:
/**
 * Use AddUuidTablemaaping to support adding uuid to base table.
 */
public function getCustomTableMapping(ContentEntityTypeInterface $entity_type, array $storage_definitions, $prefix = '') {
  $prefix = $prefix ?: ($this-&gt;temporary ? 'tmp_' : '');
  return AddUuidTableMapping::create($entity_type, $storage_definitions, $prefix);
}

Step 4: Create AddUuidTableMapping extending DefaultTableMapping and override create method.
public static function create(ContentEntityTypeInterface $entity_type, array $storage_definitions, $prefix = '') {
  $table_mapping = new static($entity_type, $storage_definitions, $prefix);

  $revisionable = $entity_type-&gt;isRevisionable();
  $translatable = $entity_type-&gt;isTranslatable();

  $id_key = $entity_type-&gt;getKey('id');
  $revision_key = $entity_type-&gt;getKey('revision');
  $bundle_key = $entity_type-&gt;getKey('bundle');
  $uuid_key = $entity_type-&gt;getKey('uuid');
  $langcode_key = $entity_type-&gt;getKey('langcode');

+ // The Magic, without this uuid will be added to dataTable if such exists.
+ if (array_key_exists('uuid', $storage_definitions)) {
+   $uuid_key = 'uuid';
+ }
+ // end Magic.

  $shared_table_definitions = array_filter($storage_definitions, function (FieldStorageDefinitionInterface $definition) use ($table_mapping) {
    return $table_mapping-&gt;allowsSharedTableStorage($definition);
  });

  $key_fields = array_values(
    array_filter(
      [$id_key, $revision_key, $bundle_key, $uuid_key, $langcode_key]
    )
  );

  $all_fields = array_keys($shared_table_definitions);
  $revisionable_fields = array_keys(array_filter($shared_table_definitions, function (FieldStorageDefinitionInterface $definition) {
    return $definition-&gt;isRevisionable();
  }));
  // Make sure the key fields come first in the list of fields.
  $all_fields = array_merge($key_fields, array_diff($all_fields, $key_fields));

  ...
}

Step 5: Create the field storage definition in post update hook:
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();

/** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $last_installed_schema_repository */
$field_storage_definition = BaseFieldDefinition::create('uuid')
  -&gt;setLabel(new TranslatableMarkup('UUID'))
  -&gt;setReadOnly(TRUE);

$definition_update_manager-&gt;installFieldStorageDefinition('uuid', $entity_type_id, 'my_custom_module', $field_storage_definition);

Step 6: Set uuid values for existing entities in baseTable:
$rows = $db_connection-&gt;select($entity_type_id, 'e')
  -&gt;fields('e', ['id'])
  -&gt;isNull('uuid')
  -&gt;execute()
  -&gt;fetchAll();

foreach ($rows as $row) {
  $db_connection-&gt;update($entity_type_id)
    -&gt;fields(['uuid' =&gt; \Drupal::service('uuid')-&gt;generate()])
    -&gt;condition('id', $row-&gt;id)
    -&gt;execute();
}

Step 7: Update entity type and field storage schema:
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();

$e = $definition_update_manager-&gt;getEntityType($entity_type_id);
$keys = $e-&gt;getKeys();
$keys['uuid'] = 'uuid';
$e-&gt;set('entity_keys', $keys);

$definition_update_manager-&gt;updateEntityType($e);
$field_storage_definition = $definition_update_manager-&gt;getFieldStorageDefinition('uuid', $entity_type_id);
$definition_update_manager-&gt;updateFieldStorageDefinition($field_storage_definition);

This last step will update the entity type definition in db + make uuid field not_null in in baseTable.
Done.
Alternate solution is to use $definition_update_manager-&gt;updateFieldableEntityType, but will require overriding storage_schema handler(assuming there are existing entities) for the entity type as it forces not_null for entity keys by default.