diff --git a/core/modules/workflows/src/ProxyClass/WorkflowsUninstallValidator.php b/core/modules/workflows/src/ProxyClass/WorkflowsUninstallValidator.php
new file mode 100644
index 0000000..a3fe435
--- /dev/null
+++ b/core/modules/workflows/src/ProxyClass/WorkflowsUninstallValidator.php
@@ -0,0 +1,88 @@
+<?php
+// @codingStandardsIgnoreFile
+
+/**
+ * This file was generated via php core/scripts/generate-proxy-class.php 'Drupal\workflows\WorkflowsUninstallValidator' "core/modules/workflows/src".
+ */
+
+namespace Drupal\workflows\ProxyClass {
+
+    /**
+     * Provides a proxy class for \Drupal\workflows\WorkflowsUninstallValidator.
+     *
+     * @see \Drupal\Component\ProxyBuilder
+     */
+    class WorkflowsUninstallValidator 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\workflows\WorkflowsUninstallValidator
+         */
+        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/core/modules/workflows/src/WorkflowsUninstallValidator.php b/core/modules/workflows/src/WorkflowsUninstallValidator.php
new file mode 100644
index 0000000..085f183
--- /dev/null
+++ b/core/modules/workflows/src/WorkflowsUninstallValidator.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace Drupal\workflows;
+
+use Drupal\Component\Plugin\PluginManagerInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+
+/**
+ * Prevents book module from being uninstalled whilst any book nodes exist or
+ * there are any book outline stored.
+ */
+class WorkflowsUninstallValidator implements ModuleUninstallValidatorInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * The workflow type plugin manager.
+   *
+   * @var \Drupal\Component\Plugin\PluginManagerInterface
+   */
+  protected $workflowTypeManager;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs a WorkflowsUninstallValidator class.
+   *
+   * @param \Drupal\Component\Plugin\PluginManagerInterface $workflow_type_manager
+   *   The workflow type plugin manager.
+
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct(PluginManagerInterface $workflow_type_manager, EntityTypeManagerInterface $entity_type_manager) {
+    $this->workflowTypeManager = $workflow_type_manager;
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validate($module) {
+    $reasons = [];
+
+    // Get a list of workflow type plugins defined by the module that is about
+    // to be uninstalled.
+    $workflow_types = [];
+    foreach ($this->workflowTypeManager->getDefinitions() as $plugin_id => $definition) {
+      if ($definition['provider'] === $module) {
+        $workflow_types[] = $plugin_id;
+      }
+    };
+
+    // Find all the workflow config entities using those workflow types and
+    // prevent the module from being uninstalled if any one of them are still in
+    // use.
+    if ($workflow_types) {
+      $workflow_ids = $this->entityTypeManager->getStorage('workflow')->getQuery()
+        ->condition('type', $workflow_types, 'IN')
+        ->execute();
+
+      /** @var \Drupal\workflows\WorkflowInterface[] $workflows */
+      $workflows = $workflow_ids ? $this->entityTypeManager->getStorage('workflow')->loadMultiple($workflow_ids) : [];
+
+      foreach ($workflows as $workflow) {
+        if ($workflow->getTypePlugin()->workflowHasData($workflow)) {
+          $reasons[] = $this->t('The %workflow_label workflow contains data.', [
+            '%workflow_label' => $workflow->label(),
+          ]);
+        }
+      }
+
+    }
+
+    return $reasons;
+  }
+
+}
diff --git a/core/modules/workflows/tests/modules/workflow_type_test/src/Plugin/WorkflowType/TestType.php b/core/modules/workflows/tests/modules/workflow_type_test/src/Plugin/WorkflowType/TestType.php
index ddd074a..26dc42f 100644
--- a/core/modules/workflows/tests/modules/workflow_type_test/src/Plugin/WorkflowType/TestType.php
+++ b/core/modules/workflows/tests/modules/workflow_type_test/src/Plugin/WorkflowType/TestType.php
@@ -3,6 +3,7 @@
 namespace Drupal\workflow_type_test\Plugin\WorkflowType;
 
 use Drupal\workflows\Plugin\WorkflowTypeBase;
+use Drupal\workflows\WorkflowInterface;
 
 /**
  * Test workflow type.
@@ -17,6 +18,13 @@ class TestType extends WorkflowTypeBase {
   /**
    * {@inheritdoc}
    */
+  public function workflowHasData(WorkflowInterface $workflow) {
+    return \Drupal::state()->get('workflow_type_test.has_data', FALSE);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getRequiredStates() {
     // Normally this is obtained from the annotation but we get from state to
     // allow dynamic testing.
diff --git a/core/modules/workflows/tests/src/Kernel/WorkflowDependenciesTest.php b/core/modules/workflows/tests/src/Kernel/WorkflowDependenciesTest.php
index c1070dc..75efcc7 100644
--- a/core/modules/workflows/tests/src/Kernel/WorkflowDependenciesTest.php
+++ b/core/modules/workflows/tests/src/Kernel/WorkflowDependenciesTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\workflows\Kernel;
 
+use Drupal\Core\Extension\ModuleUninstallValidatorException;
 use Drupal\KernelTests\KernelTestBase;
 use Drupal\workflows\Entity\Workflow;
 
@@ -38,4 +39,43 @@ public function testOnDependencyRemoval() {
     $this->assertSame(['workflow_type_test'], $workflow->getDependencies()['module']);
   }
 
+  /**
+   * Test uninstalling a module that provides a workflow type.
+   *
+   * @covers \Drupal\workflows\WorkflowsUninstallValidator::validate
+   */
+  public function testUninstallModuleWithWorkflowTypeInUse() {
+    $module_installer = \Drupal::service('module_installer');
+
+    // Create a workflow of a type for which we can control whether it is in use
+    // or not.
+    $workflow = Workflow::create([
+      'type' => 'workflow_type_test',
+      'id' => 'test_workflow',
+    ]);
+    $workflow->save();
+
+    // Simulate a workflow type that is in use.
+    \Drupal::state()->set('workflow_type_test.has_data', TRUE);
+
+    try {
+      $module_installer->uninstall(['workflow_type_test']);
+      $this->fail('A module that provides a workflow type that is in use can not be uninstalled.');
+    }
+    catch (ModuleUninstallValidatorException $e) {
+      $this->assertTrue(TRUE,'A module that provides a workflow type that is in use can not be uninstalled.');
+    }
+
+    // Simulate a workflow type that is no longer being used.
+    \Drupal::state()->set('workflow_type_test.has_data', FALSE);
+    try {
+      $module_installer->uninstall(['workflow_type_test']);
+      $this->assertTrue(TRUE,'A module that provides a workflow type that is not in use can be uninstalled.');
+
+    }
+    catch (ModuleUninstallValidatorException $e) {
+      $this->fail('A module that provides a workflow type that is not in use can be uninstalled.');
+    }
+  }
+
 }
diff --git a/core/modules/workflows/workflows.services.yml b/core/modules/workflows/workflows.services.yml
index 7d32420..0facfe0 100644
--- a/core/modules/workflows/workflows.services.yml
+++ b/core/modules/workflows/workflows.services.yml
@@ -8,3 +8,9 @@ services:
     class: \Drupal\workflows\WorkflowDeleteAccessCheck
     tags:
       - { name: access_check, applies_to: _workflow_state_delete_access }
+  workflows.uninstall_validator:
+    class: Drupal\workflows\WorkflowsUninstallValidator
+    tags:
+      - { name: module_install.uninstall_validator }
+    arguments: ['@plugin.manager.workflows.type', '@entity_type.manager']
+    lazy: true
