diff --git a/automatic_updates.install b/automatic_updates.install
index c17fad0c4cbe06923ca18e4fa2f899cc7118458b..02dbe7d52932641f045eeba2ad48cce337e11c52 100644
--- a/automatic_updates.install
+++ b/automatic_updates.install
@@ -7,6 +7,13 @@
 
 use Drupal\automatic_updates\Validation\ReadinessRequirements;
 
+/**
+ * Implements hook_uninstall().
+ */
+function automatic_updates_uninstall() {
+  \Drupal::service('automatic_updates.updater')->destroy(TRUE);
+}
+
 /**
  * Implements hook_requirements().
  */
diff --git a/package_manager/package_manager.services.yml b/package_manager/package_manager.services.yml
index 271b0428c3d6e914a6ee3e7eaabab269a59baa96..75ae35d2ece1b138391ece253096555ec0775c0a 100644
--- a/package_manager/package_manager.services.yml
+++ b/package_manager/package_manager.services.yml
@@ -137,3 +137,11 @@ services:
       - '@package_manager.path_locator'
     tags:
       - { name: event_subscriber }
+  package_manager.uninstall_validator:
+    class: Drupal\package_manager\PackageManagerUninstallValidator
+    tags:
+      - { name: module_install.uninstall_validator }
+    parent: container.trait
+    calls:
+      - ['setContainer', ['@service_container']]
+    lazy: true
diff --git a/package_manager/src/PackageManagerUninstallValidator.php b/package_manager/src/PackageManagerUninstallValidator.php
new file mode 100644
index 0000000000000000000000000000000000000000..dd9ab876071ed9f8669e22c0daf1a7c3a437fb44
--- /dev/null
+++ b/package_manager/src/PackageManagerUninstallValidator.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace Drupal\package_manager;
+
+use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+use Symfony\Component\DependencyInjection\ContainerAwareTrait;
+
+/**
+ * Prevents any module from being uninstalled if update is in process.
+ */
+class PackageManagerUninstallValidator implements ModuleUninstallValidatorInterface, ContainerAwareInterface {
+
+  use ContainerAwareTrait;
+  use StringTranslationTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validate($module) {
+    $stage = new Stage(
+      $this->container->get('config.factory'),
+      $this->container->get('package_manager.path_locator'),
+      $this->container->get('package_manager.beginner'),
+      $this->container->get('package_manager.stager'),
+      $this->container->get('package_manager.committer'),
+      $this->container->get('file_system'),
+      $this->container->get('event_dispatcher'),
+      $this->container->get('tempstore.shared'),
+      $this->container->get('datetime.time')
+    );
+    if ($stage->isAvailable() || !$stage->isApplying()) {
+      return [];
+    }
+    if ($stage->isApplying()) {
+      $reasons[] = $this->t('Modules cannot be uninstalled while Package Manager is applying staged changes to the active code base.');
+    }
+    return $reasons;
+  }
+
+}
diff --git a/package_manager/src/ProxyClass/PackageManagerUninstallValidator.php b/package_manager/src/ProxyClass/PackageManagerUninstallValidator.php
new file mode 100644
index 0000000000000000000000000000000000000000..275e878aa585bd6ac7f8a52609f7177c113966bb
--- /dev/null
+++ b/package_manager/src/ProxyClass/PackageManagerUninstallValidator.php
@@ -0,0 +1,88 @@
+<?php
+// phpcs:ignoreFile
+
+/**
+ * This file was generated via php core/scripts/generate-proxy-class.php 'Drupal\package_manager\PackageManagerUninstallValidator' "modules/contrib/automatic_updates/package_manager/src".
+ */
+
+namespace Drupal\package_manager\ProxyClass {
+
+    /**
+     * Provides a proxy class for \Drupal\package_manager\PackageManagerUninstallValidator.
+     *
+     * @see \Drupal\Component\ProxyBuilder
+     */
+    class PackageManagerUninstallValidator implements \Drupal\Core\Extension\ModuleUninstallValidatorInterface
+    {
+
+        use \Drupal\Core\DependencyInjection\DependencySerializationTrait;
+
+        /**
+         * The id of the original proxied service.
+         *
+         * @var string
+         */
+        protected $drupalProxyOriginalServiceId;
+
+        /**
+         * The real proxied service, after it was lazy loaded.
+         *
+         * @var \Drupal\package_manager\PackageManagerUninstallValidator
+         */
+        protected $service;
+
+        /**
+         * The service container.
+         *
+         * @var \Symfony\Component\DependencyInjection\ContainerInterface
+         */
+        protected $container;
+
+        /**
+         * Constructs a ProxyClass Drupal proxy object.
+         *
+         * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+         *   The container.
+         * @param string $drupal_proxy_original_service_id
+         *   The service ID of the original service.
+         */
+        public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $drupal_proxy_original_service_id)
+        {
+            $this->container = $container;
+            $this->drupalProxyOriginalServiceId = $drupal_proxy_original_service_id;
+        }
+
+        /**
+         * Lazy loads the real service from the container.
+         *
+         * @return object
+         *   Returns the constructed real service.
+         */
+        protected function lazyLoadItself()
+        {
+            if (!isset($this->service)) {
+                $this->service = $this->container->get($this->drupalProxyOriginalServiceId);
+            }
+
+            return $this->service;
+        }
+
+        /**
+         * {@inheritdoc}
+         */
+        public function validate($module)
+        {
+            return $this->lazyLoadItself()->validate($module);
+        }
+
+        /**
+         * {@inheritdoc}
+         */
+        public function setStringTranslation(\Drupal\Core\StringTranslation\TranslationInterface $translation)
+        {
+            return $this->lazyLoadItself()->setStringTranslation($translation);
+        }
+
+    }
+
+}
diff --git a/package_manager/src/Stage.php b/package_manager/src/Stage.php
index 71c4ceac261b57f039870f75e7a8e81b4236b41f..810806fe743ab728d415df8b7a9befd36c4b2ce1 100644
--- a/package_manager/src/Stage.php
+++ b/package_manager/src/Stage.php
@@ -359,12 +359,7 @@ class Stage {
     if (!$force) {
       $this->checkOwnership();
     }
-
-    // If we started applying staged changes to the active directory less than
-    // an hour ago, prevent the stage from being destroyed.
-    // @see :apply()
-    $apply_time = $this->tempStore->get(self::TEMPSTORE_APPLY_TIME_KEY);
-    if (isset($apply_time) && $this->time->getRequestTime() - $apply_time < 3600) {
+    if ($this->isApplying()) {
       throw new StageException('Cannot destroy the staging area while it is being applied to the active directory.');
     }
 
@@ -547,4 +542,21 @@ class Stage {
     return FileSystem::getOsTemporaryDirectory() . DIRECTORY_SEPARATOR . '.package_manager' . $site_id;
   }
 
+  /**
+   * Checks if staged changes are being applied to the active directory.
+   *
+   * @return bool
+   *   TRUE if the staged changes are being applied to the active directory, and
+   *   it has been less than an hour since that operation began. If more than an
+   *   hour has elapsed since the changes started to be applied, FALSE is
+   *   returned even if the stage internally thinks that changes are still being
+   *   applied.
+   *
+   * @see ::apply()
+   */
+  final public function isApplying(): bool {
+    $apply_time = $this->tempStore->get(self::TEMPSTORE_APPLY_TIME_KEY);
+    return isset($apply_time) && $this->time->getRequestTime() - $apply_time < 3600;
+  }
+
 }
diff --git a/package_manager/tests/src/Kernel/StageTest.php b/package_manager/tests/src/Kernel/StageTest.php
index 90ac26e4d9f26251fbce4b5ae45a4f3642049370..bf68cc8f39bcd6829659fc50d6021418394e3e59 100644
--- a/package_manager/tests/src/Kernel/StageTest.php
+++ b/package_manager/tests/src/Kernel/StageTest.php
@@ -4,6 +4,7 @@ namespace Drupal\Tests\package_manager\Kernel;
 
 use Drupal\Component\Datetime\Time;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\Extension\ModuleUninstallValidatorException;
 use Drupal\package_manager\Event\PostApplyEvent;
 use Drupal\package_manager\Event\PreApplyEvent;
 use Drupal\package_manager\Event\StageEvent;
@@ -12,6 +13,8 @@ use Drupal\package_manager\Exception\StageException;
 /**
  * @coversDefaultClass \Drupal\package_manager\Stage
  *
+ * @covers \Drupal\package_manager\PackageManagerUninstallValidator
+ *
  * @group package_manager
  */
 class StageTest extends PackageManagerKernelTestBase {
@@ -179,6 +182,32 @@ class StageTest extends PackageManagerKernelTestBase {
     $stage->apply();
   }
 
+  /**
+   * Test uninstalling any module while the staged changes are being applied.
+   */
+  public function testUninstallModuleDuringApply(): void {
+    $listener = function (PreApplyEvent $event): void {
+      $this->assertTrue($event->getStage()->isApplying());
+
+      // Trying to uninstall any module while the stage is being applied should
+      // result in a module uninstall validation error.
+      try {
+        $this->container->get('module_installer')
+          ->uninstall(['package_manager_bypass']);
+        $this->fail('Expected an exception to be thrown while uninstalling a module.');
+      }
+      catch (ModuleUninstallValidatorException $e) {
+        $this->assertStringContainsString('Modules cannot be uninstalled while Package Manager is applying staged changes to the active code base.', $e->getMessage());
+      }
+    };
+    $this->container->get('event_dispatcher')
+      ->addListener(PreApplyEvent::class, $listener);
+
+    $stage = $this->createStage();
+    $stage->create();
+    $stage->apply();
+  }
+
 }
 
 /**