diff --git a/core/modules/aggregator/tests/src/Kernel/Migrate/MigrateAggregatorStubTest.php b/core/modules/aggregator/tests/src/Kernel/Migrate/MigrateAggregatorStubTest.php
index 0d129c7..1ae2e9a 100644
--- a/core/modules/aggregator/tests/src/Kernel/Migrate/MigrateAggregatorStubTest.php
+++ b/core/modules/aggregator/tests/src/Kernel/Migrate/MigrateAggregatorStubTest.php
@@ -37,6 +37,13 @@ public function testFeedStub() {
   }
 
   /**
+   * Tests suppression of aggregator feed stubs.
+   */
+  public function testNoFeedStub() {
+    $this->performStubTest('aggregator_feed', TRUE);
+  }
+
+  /**
    * Tests creation of aggregator feed items.
    */
   public function testItemStub() {
@@ -55,4 +62,11 @@ public function testItemStub() {
     $this->performStubTest('aggregator_item');
   }
 
+  /**
+   * Tests suppression of aggregator item stubs.
+   */
+  public function testNoItemStub() {
+    $this->performStubTest('aggregator_item', TRUE);
+  }
+
 }
diff --git a/core/modules/block_content/tests/src/Kernel/Migrate/MigrateBlockContentStubTest.php b/core/modules/block_content/tests/src/Kernel/Migrate/MigrateBlockContentStubTest.php
index 1958039..02400c4 100644
--- a/core/modules/block_content/tests/src/Kernel/Migrate/MigrateBlockContentStubTest.php
+++ b/core/modules/block_content/tests/src/Kernel/Migrate/MigrateBlockContentStubTest.php
@@ -55,4 +55,11 @@ public function testStubSuccess() {
     $this->performStubTest('block_content');
   }
 
+  /**
+   * Tests suppression of block content stubs.
+   */
+  public function testNoStub() {
+    $this->performStubTest('block_content', TRUE);
+  }
+
 }
diff --git a/core/modules/comment/tests/src/Kernel/Migrate/MigrateCommentStubTest.php b/core/modules/comment/tests/src/Kernel/Migrate/MigrateCommentStubTest.php
index b5fc4fe..11c80f2 100644
--- a/core/modules/comment/tests/src/Kernel/Migrate/MigrateCommentStubTest.php
+++ b/core/modules/comment/tests/src/Kernel/Migrate/MigrateCommentStubTest.php
@@ -70,4 +70,11 @@ public function testStub() {
     $this->performStubTest('comment');
   }
 
+  /**
+   * Tests suppression of comment stubs.
+   */
+  public function testNoStub() {
+    $this->performStubTest('comment', TRUE);
+  }
+
 }
diff --git a/core/modules/file/tests/src/Kernel/Migrate/MigrateFileStubTest.php b/core/modules/file/tests/src/Kernel/Migrate/MigrateFileStubTest.php
index 2965086..1586ac5 100644
--- a/core/modules/file/tests/src/Kernel/Migrate/MigrateFileStubTest.php
+++ b/core/modules/file/tests/src/Kernel/Migrate/MigrateFileStubTest.php
@@ -34,4 +34,11 @@ public function testStub() {
     $this->performStubTest('file');
   }
 
+  /**
+   * Tests suppression of file stubs.
+   */
+  public function testNoStub() {
+    $this->performStubTest('file', TRUE);
+  }
+
 }
diff --git a/core/modules/menu_link_content/tests/src/Kernel/Migrate/MigrateMenuLinkContentStubTest.php b/core/modules/menu_link_content/tests/src/Kernel/Migrate/MigrateMenuLinkContentStubTest.php
index 2c348cf..f5f6450 100644
--- a/core/modules/menu_link_content/tests/src/Kernel/Migrate/MigrateMenuLinkContentStubTest.php
+++ b/core/modules/menu_link_content/tests/src/Kernel/Migrate/MigrateMenuLinkContentStubTest.php
@@ -34,4 +34,11 @@ public function testStub() {
     $this->performStubTest('menu_link_content');
   }
 
+  /**
+   * Tests suppression of menu link content stubs.
+   */
+  public function testNoStub() {
+    $this->performStubTest('menu_link_content', TRUE);
+  }
+
 }
diff --git a/core/modules/migrate/config/schema/migrate.data_types.schema.yml b/core/modules/migrate/config/schema/migrate.data_types.schema.yml
new file mode 100644
index 0000000..02bd699
--- /dev/null
+++ b/core/modules/migrate/config/schema/migrate.data_types.schema.yml
@@ -0,0 +1,40 @@
+# Basic data types for Migrate.
+
+migrate_plugin:
+  type: mapping
+  mapping:
+    plugin:
+      type: string
+      label: 'Plugin'
+
+migrate_destination:
+  type: migrate_plugin
+  label: 'Destination'
+  mapping:
+    overwrite_properties:
+      type: sequence
+      label: 'Properties to overwrite'
+      sequence:
+        type: string
+        label: 'Property'
+    no_stub:
+      type: boolean
+      label: 'Whether stubbing is allowed.'
+      default: false
+
+migrate_source:
+  type: migrate_plugin
+  label: 'Source'
+  mapping:
+    constants:
+      type: ignore
+      label: 'Constants'
+
+# Base schema for migrate source plugins that extend
+# \Drupal\migrate\Plugin\migrate\source\SqlBase.
+migrate_source_sql:
+  type: migrate_source
+  mapping:
+    target:
+      type: string
+      label: 'The migration database target'
diff --git a/core/modules/migrate/config/schema/migrate.destination.schema.yml b/core/modules/migrate/config/schema/migrate.destination.schema.yml
new file mode 100644
index 0000000..65f5bdb
--- /dev/null
+++ b/core/modules/migrate/config/schema/migrate.destination.schema.yml
@@ -0,0 +1,13 @@
+# Schema for the migrate destination plugins.
+
+migrate.destination.*:
+  type: migrate_destination
+  label: 'Default destination'
+
+migrate.destination.config:
+  type: migrate_destination
+  label: 'Config'
+  mapping:
+    config_name:
+      type: string
+      label: 'Configuration name'
diff --git a/core/modules/migrate/src/Plugin/MigrationInterface.php b/core/modules/migrate/src/Plugin/MigrationInterface.php
index 7572760..7c85ab7 100644
--- a/core/modules/migrate/src/Plugin/MigrationInterface.php
+++ b/core/modules/migrate/src/Plugin/MigrationInterface.php
@@ -142,7 +142,7 @@ public function getProcessPlugins(array $process = NULL);
    * @return \Drupal\migrate\Plugin\MigrateDestinationInterface
    *   The destination plugin.
    */
-  public function getDestinationPlugin($stub_being_requested = FALSE);
+  public function getDestinationPlugin();
 
   /**
    * Returns the initialized id_map plugin.
diff --git a/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php
index 6a2fb98..325b6b4 100644
--- a/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php
+++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php
@@ -80,6 +80,14 @@ public static function create(ContainerInterface $container, array $configuratio
    * {@inheritdoc}
    */
   public function import(Row $row, array $old_destination_id_values = array()) {
+    // If the migration process plugin is requesting a stub, and the destination
+    // configuration tells us not to create stubs, return an empty entity ID.
+    // The migration process plugin will thus return a NULL value, which any
+    // subsequent process plugins such as default_value or skip_on_empty may
+    // respond to.
+    if ($row->isStub() && !empty($this->configuration['no_stub'])) {
+      return [];
+    }
     $this->rollbackAction = MigrateIdMapInterface::ROLLBACK_DELETE;
     $entity = $this->getEntity($row, $old_destination_id_values);
     if (!$entity) {
diff --git a/core/modules/migrate/src/Plugin/migrate/process/Migration.php b/core/modules/migrate/src/Plugin/migrate/process/Migration.php
index 6a24495..13275e1 100644
--- a/core/modules/migrate/src/Plugin/migrate/process/Migration.php
+++ b/core/modules/migrate/src/Plugin/migrate/process/Migration.php
@@ -114,7 +114,7 @@ public function transform($value, MigrateExecutableInterface $migrate_executable
       else {
         $migration = reset($migrations);
       }
-      $destination_plugin = $migration->getDestinationPlugin(TRUE);
+      $destination_plugin = $migration->getDestinationPlugin();
       // Only keep the process necessary to produce the destination ID.
       $process = $migration->getProcess();
 
diff --git a/core/modules/migrate_drupal/src/Tests/StubTestTrait.php b/core/modules/migrate_drupal/src/Tests/StubTestTrait.php
index 3bf0028..a8c96a0 100644
--- a/core/modules/migrate_drupal/src/Tests/StubTestTrait.php
+++ b/core/modules/migrate_drupal/src/Tests/StubTestTrait.php
@@ -1,7 +1,9 @@
 <?php
 
 namespace Drupal\migrate_drupal\Tests;
-
+use Drupal\migrate\Entity\Migration;
+use Drupal\migrate\MigrateSkipProcessException;
+use Drupal\migrate\MigrateSkipRowException;
 use Drupal\migrate\Row;
 
 /**
@@ -15,18 +17,26 @@
    *
    * @param string $entity_type_id
    *   The entity type we are stubbing.
+   * @param boolean $no_stub
+   *   TRUE to prevent stub creation.
    */
-  protected function performStubTest($entity_type_id) {
-    $entity_id = $this->createStub($entity_type_id);
-    $this->assertTrue($entity_id, 'Stub successfully created');
-    if ($entity_id) {
-      $violations = $this->validateStub($entity_type_id, $entity_id);
-      if (!$this->assertIdentical(count($violations), 0, 'Stub is a valid entity')) {
-        foreach ($violations as $violation) {
-          $this->fail((string) $violation->getMessage());
+  protected function performStubTest($entity_type_id, $no_stub = FALSE) {
+    $entity_id = $this->createStub($entity_type_id, $no_stub);
+    if ($no_stub) {
+      $this->assertFalse($entity_id, 'Stub creation suppressed');
+    }
+    else {
+      $this->assertTrue($entity_id, 'Stub successfully created');
+      if ($entity_id) {
+        $violations = $this->validateStub($entity_type_id, $entity_id);
+        if (!$this->assertIdentical(count($violations), 0, 'Stub is a valid entity')) {
+          foreach ($violations as $violation) {
+            $this->fail((string) $violation->getMessage());
+          }
         }
       }
     }
+
   }
 
   /**
@@ -34,11 +44,13 @@ protected function performStubTest($entity_type_id) {
    *
    * @param string $entity_type_id
    *   The entity type we are stubbing.
+   * @param boolean $no_stub
+   *   TRUE to prevent stub creation.
    *
    * @return int
    *   ID of the created entity.
    */
-  protected function createStub($entity_type_id) {
+  protected function createStub($entity_type_id, $no_stub = FALSE) {
     // Create a dummy migration to pass to the destination plugin.
     $definition = [
       'migration_tags' => ['Stub test'],
@@ -46,8 +58,11 @@ protected function createStub($entity_type_id) {
       'process' => [],
       'destination' => ['plugin' => 'entity:' . $entity_type_id],
     ];
-    $migration = \Drupal::service('plugin.manager.migration')->createStubMigration($definition);
-    $destination_plugin = $migration->getDestinationPlugin(TRUE);
+    if ($no_stub) {
+      $config['destination']['no_stub'] = TRUE;
+    }
+    $migration = Migration::create($config);
+    $destination_plugin = $migration->getDestinationPlugin();
     $stub_row = new Row([], [], TRUE);
     $destination_ids = $destination_plugin->import($stub_row);
     return reset($destination_ids);
diff --git a/core/modules/node/tests/src/Kernel/Migrate/MigrateNodeStubTest.php b/core/modules/node/tests/src/Kernel/Migrate/MigrateNodeStubTest.php
index 5b393b1..034691c 100644
--- a/core/modules/node/tests/src/Kernel/Migrate/MigrateNodeStubTest.php
+++ b/core/modules/node/tests/src/Kernel/Migrate/MigrateNodeStubTest.php
@@ -40,4 +40,11 @@ public function testStub() {
     $this->performStubTest('node');
   }
 
+  /**
+   * Tests suppression of node stubs.
+   */
+  public function testNoStub() {
+    $this->performStubTest('node', TRUE);
+  }
+
 }
diff --git a/core/modules/shortcut/tests/src/Kernel/Migrate/MigrateShortcutStubTest.php b/core/modules/shortcut/tests/src/Kernel/Migrate/MigrateShortcutStubTest.php
index f5b01d9..b88c70b 100644
--- a/core/modules/shortcut/tests/src/Kernel/Migrate/MigrateShortcutStubTest.php
+++ b/core/modules/shortcut/tests/src/Kernel/Migrate/MigrateShortcutStubTest.php
@@ -36,4 +36,11 @@ public function testStub() {
     $this->performStubTest('shortcut');
   }
 
+  /**
+   * Tests suppression of shortcut stubs.
+   */
+  public function testNoStub() {
+    $this->performStubTest('shortcut', TRUE);
+  }
+
 }
diff --git a/core/modules/taxonomy/tests/src/Kernel/Migrate/MigrateTaxonomyTermStubTest.php b/core/modules/taxonomy/tests/src/Kernel/Migrate/MigrateTaxonomyTermStubTest.php
index 2da51e4..0c8856b 100644
--- a/core/modules/taxonomy/tests/src/Kernel/Migrate/MigrateTaxonomyTermStubTest.php
+++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/MigrateTaxonomyTermStubTest.php
@@ -42,6 +42,13 @@ public function testStub() {
   }
 
   /**
+   * Tests suppression of taxonomy term stubs.
+   */
+  public function testNoStub() {
+    $this->performStubTest('taxonomy_term', TRUE);
+  }
+
+  /**
    * Tests creation of stubs when weight is mapped.
    */
   public function testStubWithWeightMapping() {
diff --git a/core/modules/user/migration_templates/d6_user_picture_file.yml b/core/modules/user/migration_templates/d6_user_picture_file.yml
index e4d572a..c1497ee 100644
--- a/core/modules/user/migration_templates/d6_user_picture_file.yml
+++ b/core/modules/user/migration_templates/d6_user_picture_file.yml
@@ -19,6 +19,7 @@ process:
 destination:
   plugin: entity:file
   source_path_property: picture
+  no_stub: true
 migration_dependencies:
   # Every migration that saves into {file_managed} must have the d6_file
   # migration as an optional dependency to ensure it runs first.
diff --git a/core/modules/user/tests/src/Kernel/Migrate/MigrateUserStubTest.php b/core/modules/user/tests/src/Kernel/Migrate/MigrateUserStubTest.php
index 768f5d7..6d900bb 100644
--- a/core/modules/user/tests/src/Kernel/Migrate/MigrateUserStubTest.php
+++ b/core/modules/user/tests/src/Kernel/Migrate/MigrateUserStubTest.php
@@ -35,4 +35,11 @@ public function testStub() {
     $this->performStubTest('user');
   }
 
+  /**
+   * Tests suppression of user stubs.
+   */
+  public function testNoStub() {
+    $this->performStubTest('user', TRUE);
+  }
+
 }
