diff --git a/src/Commands/DefaultContentDeployCommands.php b/src/Commands/DefaultContentDeployCommands.php
index 0508acd..b312c4b 100644
--- a/src/Commands/DefaultContentDeployCommands.php
+++ b/src/Commands/DefaultContentDeployCommands.php
@@ -293,7 +293,7 @@ class DefaultContentDeployCommands extends DrushCommands {
     $this->displayImportResult();
 
     if (!$this->isAllSkip() && $this->io()->confirm(dt('Do you really want to continue?'))) {
-      $this->importer->import();
+      $this->importer->importBatch();
       $this->io()->success(dt('Content has been imported.'));
     }
   }
diff --git a/src/Form/ImportForm.php b/src/Form/ImportForm.php
index f857807..c3fed05 100644
--- a/src/Form/ImportForm.php
+++ b/src/Form/ImportForm.php
@@ -162,7 +162,7 @@ class ImportForm extends FormBase {
       $this->importer->setForceOverride($force_override);
       $this->importer->prepareForImport();
       $this->addResultMessage();
-      $this->importer->import();
+      $this->importer->importBatch();
     }
     catch (\Exception $exception) {
       $this->messenger->addError($exception->getMessage());
diff --git a/src/Importer.php b/src/Importer.php
index cdc5e20..0dec1bc 100644
--- a/src/Importer.php
+++ b/src/Importer.php
@@ -4,6 +4,7 @@ namespace Drupal\default_content_deploy;
 
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Database\Connection;
+use Drupal\Core\DependencyInjection\DependencySerializationTrait;
 use Drupal\Core\Entity\EntityChangedInterface;
 use Drupal\Core\Entity\EntityRepositoryInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
@@ -21,6 +22,8 @@ use Symfony\Component\Serializer\Serializer;
  */
 class Importer {
 
+  use DependencySerializationTrait;
+
   /**
    * Deploy manager.
    *
@@ -268,88 +271,147 @@ class Importer {
   }
 
   /**
-   * Import to entity.
-   *
-   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
-   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
-   * @throws \Drupal\Core\Entity\EntityStorageException
+   * Initiates the import process as a batch.
    */
-  public function import() {
-    $files = $this->dataToImport;
+  public function importBatch() {
+    $operations = [];
+    $total = count($this->dataToImport);
+    $current = 1;
+
+    // Initialize progress tracking here.
+    $context = [];
+    if (!isset($context['sandbox']['progress'])) {
+      $context['sandbox']['progress'] = 0;
+      $context['sandbox']['total'] = $total;
+    }
+
+    // Define the batch operations.
+    foreach ($this->dataToImport as $uuid => $data) {
+      $operations[] = [
+        [$this, 'importEntity'],
+        [$uuid, $data, $total, $current, $context],
+      ];
+      $current++;
+    }
+
+    // Set up batch information.
+    $batch = [
+      'title' => t('Importing Default Content'),
+      'operations' => $operations,
+      'finished' => [$this, 'importFinished'],
+    ];
+
+    batch_set($batch);
+
+    if (PHP_SAPI === 'cli') {
+      drush_backend_batch_process();
+    }
+  }
 
+  /**
+   * Imports a single entity as part of the batch process.
+   *
+   * @param string $uuid
+   *   The UUID of the entity to import.
+   * @param array $data
+   *   The data of the entity to import.
+   */
+  public function importEntity($uuid, $data, $total, $current, &$context) {
     if (PHP_SAPI === 'cli') {
       $root_user = $this->entityTypeManager->getStorage('user')->load(1);
       $this->accountSwitcher->switchTo($root_user);
     }
 
-    // All entities with entity references will be imported two times to ensure
-    // that all entity references are present and valid. Path aliases will be
-    // imported last to have a chance to rewrite them to the new ids of newly
-    // created entities.
-    for ($i = 0; $i <= 2; $i++) {
-      foreach ($files as $uuid => &$file) {
-        $entity_type = $file['entity_type_id'];
-        if ($file['status'] !== 'skip') {
-          if (
-            ($i !== 2 && $entity_type === 'path_alias') ||
-            ($i === 2 && $entity_type !== 'path_alias')
-          ) {
-            continue;
-          }
-          $this->linkManager->setLinkDomain($this->getLinkDomain($file));
-          $class = $this->entityTypeManager->getDefinition($entity_type)->getClass();
-          $needs_second_run = $this->preDenormalize($file, $entity_type);
-
-          /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
-          $entity = $this->serializer->denormalize($file['data'], $class, 'hal_json', ['request_method' => 'POST']);
-          $entity->enforceIsNew($file['is_new']);
-          $entity->save();
-          $this->entityIdLookup[$uuid] = $entity->id();
-
-          if ($entity_type === 'user') {
-            // Workaround: store the hashed password directly in the database
-            // and avoid the entity API which doesn't provide support for
-            // setting password hashes directly.
-            $hashed_pass = $file['data']['pass'][0]['value'] ?? FALSE;
-            if ($hashed_pass) {
-              $this->database->update('users_field_data')
-                ->fields([
-                  'pass' => $hashed_pass,
-                ])
-                ->condition('uid', $entity->id(), '=')
-                ->execute();
-            }
-          }
+    $entity_type_id = $data['entity_type_id'];
+    $entity_type_object = $this->entityTypeManager->getDefinition($entity_type_id);
 
-          if ((!$needs_second_run && empty($file['references'])) || $i === 1) {
-            // Don't handle entities without references twice. Don't handle
-            // entities with references again in the third run for path aliases.
-            unset($files[$uuid]);
-          }
-          else {
-            // In the second run new entities should be updated.
-            $file['status'] = 'update';
-            $file['is_new'] = FALSE;
-            $file['data'][$file['key_id']][0]['value'] = $entity->id();
-          }
-        }
-        elseif ($i === 0) {
-          // Get the entity ID of a skipped referenced item in the first run to
-          // enable a target ID correction in referencing entities in the second
-          // and third run.
-          $entity = $this->entityRepository->loadEntityByUuid($entity_type, $uuid);
-          $this->entityIdLookup[$uuid] = $entity->id();
-        }
+    // Keys of entity.
+    $key_id = $entity_type_object->getKey('id');
+    $key_revision_id = $entity_type_object->getKey('revision');
+
+    // Check if the entity already exists.
+    $entity = $this->entityRepository->loadEntityByUuid($entity_type_id, $uuid);
+
+    if ($entity) {
+      // Entity already exists, update it.
+      $this->linkManager->setLinkDomain($this->getLinkDomain($data));
+      $current_entity_decoded = $this->serializer->decode($this->exporter->getSerializedContent($entity), 'hal_json');
+      $diff = ArrayDiffMultidimensional::looseComparison($data['data'], $current_entity_decoded);
+
+      // Update the entity if it's different from the existing one.
+      if ($diff) {
+        $this->preAddToImport($data);
+        $this->addToImport($data);
+        $data['status'] = 'update';
+        $data['is_new'] = FALSE;
+      }
+      else {
+        $data['status'] = 'skip';
       }
-      unset($file);
+
+      // @todo is this still needed?
+      $this->linkManager->setLinkDomain(FALSE);
     }
+    else {
+      // Entity doesn't exist, create it.
+      $this->linkManager->setLinkDomain($this->getLinkDomain($data));
+      $class = $entity_type_object->getClass();
+      $entity = $this->serializer->denormalize($data['data'], $class, 'hal_json', ['request_method' => 'POST']);
+      $entity->enforceIsNew($data['is_new']);
+      $entity->save();
+      $this->entityIdLookup[$uuid] = $entity->id();
+
+      // If the entity type is 'user', update the password directly in the database.
+      if ($entity_type_id === 'user') {
+        $hashed_pass = $data['data']['pass'][0]['value'] ?? FALSE;
+        if ($hashed_pass) {
+          $this->database->update('users_field_data')
+            ->fields([
+              'pass' => $hashed_pass,
+            ])
+            ->condition('uid', $entity->id(), '=')
+            ->execute();
+        }
+      }
+
+      // Record the entity lookup.
+      if (isset($data['data'][$key_id][0]['value'])) {
+        $this->entityLookup[$entity_type_id][$data['data'][$key_id][0]['value']] = $uuid;
+      }
 
-    // @todo is this still needed?
-    $this->linkManager->setLinkDomain(FALSE);
+      // Add the entity to import.
+      $this->preAddToImport($data);
+      $this->addToImport($data);
+      $data['status'] = 'create';
+    }
 
     if (PHP_SAPI === 'cli') {
       $this->accountSwitcher->switchBack();
     }
+
+    // Provide feedback and update progress.
+    $completion_percentage = $current / $total;
+    $context['finished'] = $completion_percentage;
+    $context['message'] = t('Importing entity @current of @total', ['@current' => $current, '@total' => $total]);
+    $context['results']['processed'] = $current;
+    $context['sandbox']['progress']++;
+  }
+
+  /**
+   * Callback function to handle batch processing completion.
+   *
+   * @param bool $success
+   *   Indicates whether the batch processing was successful.
+   */
+  public function importFinished($success, $results, $operations) {
+    if ($success) {
+      // Batch processing completed successfully.
+      \Drupal::messenger()->addMessage(t('Batch import completed successfully.'));
+    }
+    else {
+      // Batch processing encountered an error.
+      \Drupal::messenger()->addMessage(t('An error occurred during the batch import process.'), 'error');
+    }
   }
 
   /**
