diff --git a/core/modules/content_moderation/content_moderation.services.yml b/core/modules/content_moderation/content_moderation.services.yml
index 904bc0dc33..256095a03a 100644
--- a/core/modules/content_moderation/content_moderation.services.yml
+++ b/core/modules/content_moderation/content_moderation.services.yml
@@ -19,4 +19,9 @@ services:
     class: Drupal\content_moderation\RevisionTracker
     arguments: ['@database']
     tags:
-     - { name: backend_overridable }
+      - { name: backend_overridable }
+  content_moderation.config_import_subscriber:
+    class: Drupal\content_moderation\EventSubscriber\ConfigImportSubscriber
+    arguments: ['@config.manager', '@entity_type.manager']
+    tags:
+      - { name: event_subscriber }
diff --git a/core/modules/content_moderation/src/EventSubscriber/ConfigImportSubscriber.php b/core/modules/content_moderation/src/EventSubscriber/ConfigImportSubscriber.php
new file mode 100644
index 0000000000..ab8e5802bb
--- /dev/null
+++ b/core/modules/content_moderation/src/EventSubscriber/ConfigImportSubscriber.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace Drupal\content_moderation\EventSubscriber;
+
+use Drupal\Core\Config\ConfigImporterEvent;
+use Drupal\Core\Config\ConfigImportValidateEventSubscriberBase;
+use Drupal\Core\Config\ConfigManagerInterface;
+use Drupal\Core\Config\Entity\ConfigEntityStorage;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+
+/**
+ * Check moderation states are not being used before updating workflow config.
+ */
+class ConfigImportSubscriber extends ConfigImportValidateEventSubscriberBase  {
+
+  /**
+   * The config manager.
+   *
+   * @var \Drupal\Core\Config\ConfigManagerInterface
+   */
+  protected $configManager;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs the event subscriber.
+   *
+   * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
+   *   The config manager
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct(ConfigManagerInterface $config_manager, EntityTypeManagerInterface $entity_type_manager) {
+    $this->configManager = $config_manager;
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function onConfigImporterValidate(ConfigImporterEvent $event) {
+    foreach (['update', 'delete'] as $op) {
+      $unprocessed_configurations = $event->getConfigImporter()->getUnprocessedConfiguration($op);
+      foreach ($unprocessed_configurations as $unprocessed_configuration) {
+        if ($workflow = $this->getWorkflow($unprocessed_configuration)) {
+          if ($op == 'update') {
+            $original_workflow_config = $event->getConfigImporter()
+              ->getStorageComparer()
+              ->getSourceStorage()
+              ->read($unprocessed_configuration);
+            $workflow_config = $event->getConfigImporter()
+              ->getStorageComparer()
+              ->getTargetStorage()
+              ->read($unprocessed_configuration);
+            $diff = array_diff_key($workflow_config['states'], $original_workflow_config['states']);
+            foreach (array_keys($diff) as $state_id) {
+              $state = $workflow->getState($state_id);
+              if ($workflow->getTypePlugin()->workflowStateHasData($workflow, $state)) {
+                $event->getConfigImporter()->logError($this->t('The moderation state @state_label is being used, but is not in the source storage.', ['@state_label' => $state->label()]));
+              }
+            }
+          }
+          if ($op == 'delete') {
+            if ($workflow->getTypePlugin()->workflowHasData($workflow)) {
+              $event->getConfigImporter()->logError($this->t('The workflow @workflow_label is being used, and cannot be deleted.', ['@workflow_label' => $workflow->label()]));
+            }
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Get the workflow entity object from the configuration name.
+   *
+   * @param string $config_name
+   *   The configuration object name.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface|null
+   *   An entity object. NULL if no matching entity is found.
+   */
+  protected function getWorkflow($config_name) {
+    $entity_type_id = $this->configManager->getEntityTypeIdByName($config_name);
+    /** @var \Drupal\Core\Config\Entity\ConfigEntityTypeInterface $entity_type */
+    $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
+    $entity_id = ConfigEntityStorage::getIDFromConfigName($config_name, $entity_type->getConfigPrefix());
+    /** @var \Drupal\workflows\WorkflowInterface $workflow */
+    return $this->entityTypeManager->getStorage($entity_type_id)->load($entity_id);
+  }
+
+}
diff --git a/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php b/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php
index b80ccdda87..37d7529884 100644
--- a/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php
+++ b/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php
@@ -131,6 +131,31 @@ public function decorateState(StateInterface $state) {
   /**
    * {@inheritdoc}
    */
+  public function workflowHasData(WorkflowInterface $workflow) {
+    return (bool) $this->entityTypeManager
+      ->getStorage('content_moderation_state')
+      ->getQuery()
+      ->count()
+      ->condition('workflow', $workflow->id())
+      ->execute();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function workflowStateHasData(WorkflowInterface $workflow, StateInterface $state) {
+    return (bool) $this->entityTypeManager
+      ->getStorage('content_moderation_state')
+      ->getQuery()
+      ->count()
+      ->condition('workflow', $workflow->id())
+      ->condition('moderation_state', $state->id())
+      ->execute();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function buildStateConfigurationForm(FormStateInterface $form_state, WorkflowInterface $workflow, StateInterface $state = NULL) {
     /** @var \Drupal\content_moderation\ContentModerationState $state */
     $is_required_state = isset($state) ? in_array($state->id(), $this->getRequiredStates(), TRUE) : FALSE;
diff --git a/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php b/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php
index 7aab0d46c3..683998b764 100644
--- a/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php
+++ b/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\content_moderation\Functional;
 
+use Drupal\Core\Entity\EntityStorageException;
 use Drupal\workflows\Entity\Workflow;
 
 /**
@@ -451,4 +452,58 @@ public function testContentTranslationNodeForm() {
     $this->drupalPostForm(NULL, [], t('Save and Create New Draft (this translation)'));
   }
 
+  /**
+   * Tests ContentModeration::isWorkflowUsed().
+   *
+   * @covers \Drupal\content_moderation\Plugin\WorkflowType\ContentModeration::workflowHasData
+   */
+  public function testWorkflowInUse() {
+    $this->drupalLogin($this->rootUser);
+    $paths = [
+      'archived_state' => 'admin/config/workflow/workflows/manage/editorial/state/archived/delete',
+      'editorial_workflow' => 'admin/config/workflow/workflows/manage/editorial/delete',
+    ];
+    foreach ($paths as $path) {
+      $this->drupalGet($path);
+      $this->assertSession()->buttonExists('Delete');
+    }
+    // Create new moderated content in draft.
+    $this->drupalPostForm('node/add/moderated_content', [
+      'title[0][value]' => 'Some moderated content',
+      'body[0][value]' => 'First version of the content.',
+    ], t('Save and Create New Draft'));
+    // The archived state is not used yet, so can still be deleted.
+    $this->drupalGet($paths['archived_state']);
+    $this->assertSession()->buttonExists('Delete');
+    // The workflow is being used, so can't be deleted.
+    $this->drupalGet($paths['editorial_workflow']);
+    $this->assertSession()->buttonNotExists('Delete');
+
+    $node = $this->drupalGetNodeByTitle('Some moderated content');
+    $this->drupalPostForm('node/' . $node->id() . '/edit', [], t('Save and Publish'));
+    $this->drupalPostForm('node/' . $node->id() . '/edit', [], t('Save and Archive'));
+    // Now the archived state is being used it can't be deleted either.
+    foreach ($paths as $path) {
+      $this->drupalGet($path);
+      $this->assertSession()->buttonNotExists('Delete');
+    }
+
+    // Test the workflow or state can't be removed via the API either.
+    $workflow = Workflow::load('editorial');
+    try {
+      $workflow->deleteState('archived');
+      $this->fail();
+    }
+    catch (EntityStorageException $e) {
+      $this->assertTrue(TRUE);
+    }
+    try {
+      $workflow->delete();
+      $this->fail();
+    }
+    catch (EntityStorageException $e) {
+      $this->assertTrue(TRUE);
+    }
+  }
+
 }
diff --git a/core/modules/content_moderation/tests/src/Kernel/ContentModerationWorkflowConfigTest.php b/core/modules/content_moderation/tests/src/Kernel/ContentModerationWorkflowConfigTest.php
new file mode 100644
index 0000000000..0680bf1f26
--- /dev/null
+++ b/core/modules/content_moderation/tests/src/Kernel/ContentModerationWorkflowConfigTest.php
@@ -0,0 +1,147 @@
+<?php
+
+namespace Drupal\Tests\content_moderation\Kernel;
+
+use Drupal\Core\Config\ConfigImporterException;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\node\Entity\Node;
+use Drupal\node\Entity\NodeType;
+use Drupal\workflows\Entity\Workflow;
+
+/**
+ * Tests how Content Moderation handles workflow config changes.
+ *
+ * @group content_moderation
+ */
+class ContentModerationWorkflowConfigTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'node',
+    'content_moderation',
+    'user',
+    'system',
+    'text',
+    'workflows',
+  ];
+
+  /**
+   * @var \Drupal\Core\Entity\EntityTypeManager
+   */
+  protected $entityTypeManager;
+
+  /**
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
+   * @var \Drupal\workflows\Entity\Workflow
+   */
+  protected $workflow;
+
+  /**
+   * @var \Drupal\Core\Config\Entity\ConfigEntityStorage
+   */
+  protected $workflowStorage;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->installSchema('node', 'node_access');
+    $this->installEntitySchema('node');
+    $this->installEntitySchema('user');
+    $this->installEntitySchema('content_moderation_state');
+    $this->installConfig('content_moderation');
+
+    NodeType::create([
+      'type' => 'example',
+    ])->save();
+
+    $workflow = Workflow::load('editorial');
+    $workflow->addState('test1', 'Test one');
+    $workflow->addState('test2', 'Test two');
+    $workflow->addState('test3', 'Test three');
+    $workflow->getTypePlugin()->setConfiguration([
+      'states' => [
+        'test1' => [
+          'published' => TRUE,
+          'default_revision' => TRUE,
+        ],
+        'test2' => [
+          'published' => TRUE,
+          'default_revision' => TRUE,
+        ],
+        'test3' => [
+          'published' => TRUE,
+          'default_revision' => TRUE,
+        ],
+      ],
+    ]);
+    $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
+    $workflow->save();
+    $this->workflow = $workflow;
+
+    $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync'));
+  }
+
+  /**
+   * Test deleting a state via config import.
+   */
+  public function testDeletingStateViaConfiguration() {
+    $config_data = $this->config('workflows.workflow.editorial')->get();
+    unset($config_data['states']['test1']);
+    \Drupal::service('config.storage.sync')->write('workflows.workflow.editorial', $config_data);
+
+    // There are no Nodes with the moderation state test1, so this should run
+    // with no errors.
+    $this->configImporter()->reset()->import();
+
+    $node = Node::create([
+      'type' => 'example',
+      'title' => 'Test title',
+      'moderation_state' => 'test2',
+    ]);
+    $node->save();
+
+    $config_data = $this->config('workflows.workflow.editorial')->get();
+    unset($config_data['states']['test2']);
+    unset($config_data['states']['test3']);
+    \Drupal::service('config.storage.sync')->write('workflows.workflow.editorial', $config_data);
+
+    // Now there is a Node with the moderation state test2, this will fail.
+    try {
+      $this->configImporter()->reset()->import();
+      $this->fail('ConfigImporterException not thrown, invalid import was not stopped due to deleted state.');
+    }
+    catch (ConfigImporterException $e) {
+      $this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.');
+      $error_log = $this->configImporter->getErrors();
+      $expected = ['The moderation state Test two is being used, but is not in the source storage.'];
+      $this->assertEqual($expected, $error_log);
+    }
+
+    \Drupal::service('config.storage.sync')->delete('workflows.workflow.editorial');
+
+    // An error should be thrown when trying to delete an in use workflow.
+    try {
+      $this->configImporter()->reset()->import();
+      $this->fail('ConfigImporterException not thrown, invalid import was not stopped due to deleted workflow.');
+    }
+    catch (ConfigImporterException $e) {
+      $this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.');
+      $error_log = $this->configImporter->getErrors();
+      $expected = [
+        'The moderation state Test two is being used, but is not in the source storage.',
+        'The workflow Editorial workflow is being used, and cannot be deleted.',
+      ];
+      $this->assertEqual($expected, $error_log);
+    }
+  }
+
+}
diff --git a/core/modules/workflows/src/Entity/Workflow.php b/core/modules/workflows/src/Entity/Workflow.php
index 51bdda2b24..e4e8823b67 100644
--- a/core/modules/workflows/src/Entity/Workflow.php
+++ b/core/modules/workflows/src/Entity/Workflow.php
@@ -3,6 +3,7 @@
 namespace Drupal\workflows\Entity;
 
 use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\Core\Entity\EntityStorageException;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
 use Drupal\Core\Plugin\DefaultSingleLazyPluginCollection;
@@ -245,6 +246,9 @@ public function deleteState($state_id) {
     if (count($this->states) === 1) {
       throw new \InvalidArgumentException("The state '$state_id' can not be deleted from workflow '{$this->id()}' as it is the only state");
     }
+    if ($this->getTypePlugin()->workflowStateHasData($this, $this->getState($state_id))) {
+      throw new EntityStorageException("The state '{$state_id}' is in use. You cannot remove this state until you have removed all content using it.");
+    }
 
     foreach ($this->transitions as $transition_id => $transition) {
       $from_key = array_search($state_id, $transition['from'], TRUE);
@@ -265,6 +269,18 @@ public function deleteState($state_id) {
   }
 
   /**
+   * @inheritDoc
+   */
+  public static function preDelete(EntityStorageInterface $storage, array $entities) {
+    foreach ($entities as $entity) {
+      if ($entity->getTypePlugin()->workflowHasData($entity)) {
+        throw new EntityStorageException("This '{$entity->label()}' workflow is in use. You cannot remove this workflow until you have removed all content using it.");
+      }
+    }
+    parent::preDelete($storage, $entities);
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function addTransition($transition_id, $label, array $from_state_ids, $to_state_id) {
diff --git a/core/modules/workflows/src/Form/WorkflowDeleteForm.php b/core/modules/workflows/src/Form/WorkflowDeleteForm.php
index b9b833132b..e122f40543 100644
--- a/core/modules/workflows/src/Form/WorkflowDeleteForm.php
+++ b/core/modules/workflows/src/Form/WorkflowDeleteForm.php
@@ -14,6 +14,19 @@ class WorkflowDeleteForm extends EntityConfirmFormBase {
   /**
    * {@inheritdoc}
    */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    if ($this->entity->getTypePlugin()->workflowHasData($this->entity)) {
+      $form['#title'] = $this->getQuestion();
+      $form['description'] = ['#markup' => $this->t('This workflow is in use. You cannot remove this workflow until you have removed all content using it.')];
+      return $form;
+    }
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getQuestion() {
     return $this->t('Are you sure you want to delete %name?', ['%name' => $this->entity->label()]);
   }
diff --git a/core/modules/workflows/src/Form/WorkflowStateDeleteForm.php b/core/modules/workflows/src/Form/WorkflowStateDeleteForm.php
index c60045ca23..d2c30d7435 100644
--- a/core/modules/workflows/src/Form/WorkflowStateDeleteForm.php
+++ b/core/modules/workflows/src/Form/WorkflowStateDeleteForm.php
@@ -75,6 +75,13 @@ public function buildForm(array $form, FormStateInterface $form_state, WorkflowI
     }
     $this->workflow = $workflow;
     $this->stateId = $workflow_state;
+
+    if ($this->workflow->getTypePlugin()->workflowStateHasData($this->workflow, $this->workflow->getState($this->stateId))) {
+      $form['#title'] = $this->getQuestion();
+      $form['description'] = ['#markup' => $this->t('This workflow state is in use. You cannot remove this workflow state until you have removed all content using it.')];
+      return $form;
+    }
+
     return parent::buildForm($form, $form_state);
   }
 
diff --git a/core/modules/workflows/src/Plugin/WorkflowTypeBase.php b/core/modules/workflows/src/Plugin/WorkflowTypeBase.php
index 34af735e3d..394658bc8e 100644
--- a/core/modules/workflows/src/Plugin/WorkflowTypeBase.php
+++ b/core/modules/workflows/src/Plugin/WorkflowTypeBase.php
@@ -58,6 +58,20 @@ public function checkWorkflowAccess(WorkflowInterface $entity, $operation, Accou
   /**
    * {@inheritdoc}
    */
+  public function workflowHasData(WorkflowInterface $workflow) {
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function workflowStateHasData(WorkflowInterface $workflow, StateInterface $state) {
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function decorateState(StateInterface $state) {
     return $state;
   }
diff --git a/core/modules/workflows/src/WorkflowTypeInterface.php b/core/modules/workflows/src/WorkflowTypeInterface.php
index 2412bf99f4..5af5c6512b 100644
--- a/core/modules/workflows/src/WorkflowTypeInterface.php
+++ b/core/modules/workflows/src/WorkflowTypeInterface.php
@@ -57,6 +57,30 @@ public function label();
   public function checkWorkflowAccess(WorkflowInterface $entity, $operation, AccountInterface $account);
 
   /**
+   * Determines if the workflow is being has data associated with it.
+   *
+   * @param \Drupal\workflows\WorkflowInterface $workflow
+   *   The workflow to check.
+   *
+   * @return bool
+   *   TRUE if the workflow is being used, FALSE if not.
+   */
+  public function workflowHasData(WorkflowInterface $workflow);
+
+  /**
+   * Determines if the workflow state has data associated with it.
+   *
+   * @param \Drupal\workflows\WorkflowInterface $workflow
+   *   The workflow to check.
+   * @param \Drupal\workflows\StateInterface $state
+   *   The workflow state to check.
+   *
+   * @return bool
+   *   TRUE if the workflow state is being used, FALSE if not.
+   */
+  public function workflowStateHasData(WorkflowInterface $workflow, StateInterface $state);
+
+  /**
    * Decorates states so the WorkflowType can add additional information.
    *
    * @param \Drupal\workflows\StateInterface $state
