diff --git a/core/modules/aggregator/migration_templates/d6_aggregator_item.yml b/core/modules/aggregator/migration_templates/d6_aggregator_item.yml
index fb4040a..e14dbd6 100644
--- a/core/modules/aggregator/migration_templates/d6_aggregator_item.yml
+++ b/core/modules/aggregator/migration_templates/d6_aggregator_item.yml
@@ -7,7 +7,7 @@ source:
 process:
   iid: iid
   fid:
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_aggregator_feed
     source: fid
   title: title
diff --git a/core/modules/aggregator/migration_templates/d7_aggregator_item.yml b/core/modules/aggregator/migration_templates/d7_aggregator_item.yml
index 9735e19..054ba43 100644
--- a/core/modules/aggregator/migration_templates/d7_aggregator_item.yml
+++ b/core/modules/aggregator/migration_templates/d7_aggregator_item.yml
@@ -7,7 +7,7 @@ source:
 process:
   iid: iid
   fid:
-    plugin: migration
+    plugin: migration_lookup
     migration: d7_aggregator_feed
     source: fid
   title: title
diff --git a/core/modules/block_content/migration_templates/d6_custom_block.yml b/core/modules/block_content/migration_templates/d6_custom_block.yml
index 8394c64..55fbcb5 100644
--- a/core/modules/block_content/migration_templates/d6_custom_block.yml
+++ b/core/modules/block_content/migration_templates/d6_custom_block.yml
@@ -8,7 +8,7 @@ process:
   id: bid
   info: info
   'body/format':
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_filter_format
     source: format
   'body/value': body
diff --git a/core/modules/block_content/migration_templates/d7_custom_block.yml b/core/modules/block_content/migration_templates/d7_custom_block.yml
index 42021fb..ca06cf0 100644
--- a/core/modules/block_content/migration_templates/d7_custom_block.yml
+++ b/core/modules/block_content/migration_templates/d7_custom_block.yml
@@ -8,7 +8,7 @@ process:
   id: bid
   info: info
   'body/format':
-    plugin: migration
+    plugin: migration_lookup
     migration: d7_filter_format
     source: format
   'body/value': body
diff --git a/core/modules/book/migration_templates/d6_book.yml b/core/modules/book/migration_templates/d6_book.yml
index f5020c3..94d7a8f 100644
--- a/core/modules/book/migration_templates/d6_book.yml
+++ b/core/modules/book/migration_templates/d6_book.yml
@@ -14,7 +14,7 @@ process:
       method: process
       source: plid
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_book
 destination:
   plugin: book
diff --git a/core/modules/comment/migration_templates/d6_comment.yml b/core/modules/comment/migration_templates/d6_comment.yml
index f4dff98..06820d4 100644
--- a/core/modules/comment/migration_templates/d6_comment.yml
+++ b/core/modules/comment/migration_templates/d6_comment.yml
@@ -11,7 +11,7 @@ process:
   # the cid field to allow incremental migrations.
   cid: cid
   pid:
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_comment
     source: pid
   entity_id: nid
@@ -32,7 +32,7 @@ process:
   thread: thread
   'comment_body/value': comment
   'comment_body/format':
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_filter_format
     source: format
 destination:
diff --git a/core/modules/comment/migration_templates/d7_comment.yml b/core/modules/comment/migration_templates/d7_comment.yml
index d4e3c57..94a2884 100644
--- a/core/modules/comment/migration_templates/d7_comment.yml
+++ b/core/modules/comment/migration_templates/d7_comment.yml
@@ -11,7 +11,7 @@ process:
   # the cid field to allow incremental migrations.
   cid: cid
   pid:
-    plugin: migration
+    plugin: migration_lookup
     migration: d7_comment
     source: pid
   entity_id: nid
diff --git a/core/modules/contact/migration_templates/d6_contact_settings.yml b/core/modules/contact/migration_templates/d6_contact_settings.yml
index 452ebb2..dbe0205 100644
--- a/core/modules/contact/migration_templates/d6_contact_settings.yml
+++ b/core/modules/contact/migration_templates/d6_contact_settings.yml
@@ -11,7 +11,7 @@ process:
   user_default_enabled: contact_default_status
   'flood/limit': contact_hourly_threshold
   default_form:
-    plugin: migration
+    plugin: migration_lookup
     migration: contact_category
     source: default_category
 destination:
diff --git a/core/modules/contact/migration_templates/d7_contact_settings.yml b/core/modules/contact/migration_templates/d7_contact_settings.yml
index a0f3a3b..9feebe5 100644
--- a/core/modules/contact/migration_templates/d7_contact_settings.yml
+++ b/core/modules/contact/migration_templates/d7_contact_settings.yml
@@ -11,7 +11,7 @@ process:
   user_default_enabled: contact_default_status
   'flood/limit': contact_threshold_limit
   default_form:
-    plugin: migration
+    plugin: migration_lookup
     migration: contact_category
     source: default_category
 destination:
diff --git a/core/modules/field/migration_templates/d6_field_formatter_settings.yml b/core/modules/field/migration_templates/d6_field_formatter_settings.yml
index 7496db3..d604491 100644
--- a/core/modules/field/migration_templates/d6_field_formatter_settings.yml
+++ b/core/modules/field/migration_templates/d6_field_formatter_settings.yml
@@ -15,7 +15,7 @@ process:
   # field migration.
   field_type_exists:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_field
       source:
         - field_name
@@ -29,7 +29,7 @@ process:
   entity_type: 'constants/entity_type'
   bundle:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_node_type
       source: type_name
     -
@@ -37,7 +37,7 @@ process:
       method: row
   view_mode:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_view_modes
       source:
         - view_mode
diff --git a/core/modules/field/migration_templates/d6_field_instance.yml b/core/modules/field/migration_templates/d6_field_instance.yml
index b5035c2..1934303 100644
--- a/core/modules/field/migration_templates/d6_field_instance.yml
+++ b/core/modules/field/migration_templates/d6_field_instance.yml
@@ -14,7 +14,7 @@ process:
   # field migration.
   field_type_exists:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_field
       source:
         - field_name
@@ -29,7 +29,7 @@ process:
   field_name: field_name
   bundle:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_node_type
       source: type_name
     -
diff --git a/core/modules/field/migration_templates/d6_field_instance_widget_settings.yml b/core/modules/field/migration_templates/d6_field_instance_widget_settings.yml
index 46b7d75..311a132 100644
--- a/core/modules/field/migration_templates/d6_field_instance_widget_settings.yml
+++ b/core/modules/field/migration_templates/d6_field_instance_widget_settings.yml
@@ -16,7 +16,7 @@ process:
   # field migration.
   field_type_exists:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_field
       source:
         - field_name
@@ -29,7 +29,7 @@ process:
       method: row
   bundle:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_node_type
       source: type_name
     -
diff --git a/core/modules/field/migration_templates/d7_field_formatter_settings.yml b/core/modules/field/migration_templates/d7_field_formatter_settings.yml
index 14cdd66..126fd29 100644
--- a/core/modules/field/migration_templates/d7_field_formatter_settings.yml
+++ b/core/modules/field/migration_templates/d7_field_formatter_settings.yml
@@ -13,7 +13,7 @@ process:
   # field migration.
   field_type_exists:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d7_field
       source:
         - field_name
@@ -29,7 +29,7 @@ process:
   bundle: bundle
   view_mode:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d7_view_modes
       source:
         - entity_type
diff --git a/core/modules/field/migration_templates/d7_field_instance_widget_settings.yml b/core/modules/field/migration_templates/d7_field_instance_widget_settings.yml
index b5ee417..e2bbcf4 100644
--- a/core/modules/field/migration_templates/d7_field_instance_widget_settings.yml
+++ b/core/modules/field/migration_templates/d7_field_instance_widget_settings.yml
@@ -14,7 +14,7 @@ process:
   # field migration.
   field_type_exists:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d7_field
       source:
         - field_name
diff --git a/core/modules/file/migration_templates/d6_upload.yml b/core/modules/file/migration_templates/d6_upload.yml
index 75164a8..8289d56 100644
--- a/core/modules/file/migration_templates/d6_upload.yml
+++ b/core/modules/file/migration_templates/d6_upload.yml
@@ -13,7 +13,7 @@ process:
     source: upload
     process:
       target_id:
-        plugin: migration
+        plugin: migration_lookup
         migration: d6_file
         source: fid
       display: list
diff --git a/core/modules/file/migration_templates/d6_upload_field_instance.yml b/core/modules/file/migration_templates/d6_upload_field_instance.yml
index 5bd7c9a..732153a 100644
--- a/core/modules/file/migration_templates/d6_upload_field_instance.yml
+++ b/core/modules/file/migration_templates/d6_upload_field_instance.yml
@@ -13,7 +13,7 @@ process:
   entity_type: 'constants/entity_type'
   bundle:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_node_type
       source: node_type
     -
diff --git a/core/modules/forum/migration_templates/d6_forum_settings.yml b/core/modules/forum/migration_templates/d6_forum_settings.yml
index 5516848..18ba8d4 100644
--- a/core/modules/forum/migration_templates/d6_forum_settings.yml
+++ b/core/modules/forum/migration_templates/d6_forum_settings.yml
@@ -18,7 +18,7 @@ process:
   'topics/page_limit': forum_per_page
   'topics/order': forum_order
   vocabulary:
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_taxonomy_vocabulary
     source: forum_nav_vocabulary
 destination:
diff --git a/core/modules/forum/migration_templates/d7_forum_settings.yml b/core/modules/forum/migration_templates/d7_forum_settings.yml
index b84d485..086d3e6 100644
--- a/core/modules/forum/migration_templates/d7_forum_settings.yml
+++ b/core/modules/forum/migration_templates/d7_forum_settings.yml
@@ -18,7 +18,7 @@ process:
   'topics/page_limit': forum_per_page
   'topics/order': forum_order
   vocabulary:
-    plugin: migration
+    plugin: migration_lookup
     migration: d7_taxonomy_vocabulary
     source: forum_nav_vocabulary
 destination:
diff --git a/core/modules/menu_link_content/migration_templates/d6_menu_links.yml b/core/modules/menu_link_content/migration_templates/d6_menu_links.yml
index c418bfe..2c8ad4a 100644
--- a/core/modules/menu_link_content/migration_templates/d6_menu_links.yml
+++ b/core/modules/menu_link_content/migration_templates/d6_menu_links.yml
@@ -10,7 +10,7 @@ process:
   description: description
   menu_name:
     -
-      plugin: migration
+      plugin: migration_lookup
       # The menu migration is in the system module.
       migration: d6_menu
       source: menu_name
diff --git a/core/modules/menu_link_content/migration_templates/d7_menu_links.yml b/core/modules/menu_link_content/migration_templates/d7_menu_links.yml
index 7f049f7..200a792 100644
--- a/core/modules/menu_link_content/migration_templates/d7_menu_links.yml
+++ b/core/modules/menu_link_content/migration_templates/d7_menu_links.yml
@@ -13,7 +13,7 @@ process:
   description: description
   menu_name:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d7_menu
       source: menu_name
     -
diff --git a/core/modules/migrate/src/Plugin/migrate/process/DefaultValue.php b/core/modules/migrate/src/Plugin/migrate/process/DefaultValue.php
index 5829f74..a5e6388 100644
--- a/core/modules/migrate/src/Plugin/migrate/process/DefaultValue.php
+++ b/core/modules/migrate/src/Plugin/migrate/process/DefaultValue.php
@@ -27,7 +27,7 @@
  * process:
  *   uid:
  *     -
- *       plugin: migration
+ *       plugin: migration_lookup
  *       migration: users
  *       source: author
  *     -
diff --git a/core/modules/migrate/src/Plugin/migrate/process/Migration.php b/core/modules/migrate/src/Plugin/migrate/process/Migration.php
index e07505f..abb92db 100644
--- a/core/modules/migrate/src/Plugin/migrate/process/Migration.php
+++ b/core/modules/migrate/src/Plugin/migrate/process/Migration.php
@@ -2,17 +2,6 @@
 
 namespace Drupal\migrate\Plugin\migrate\process;
 
-use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Drupal\migrate\MigrateSkipProcessException;
-use Drupal\migrate\Plugin\MigratePluginManagerInterface;
-use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
-use Drupal\migrate\Plugin\MigrateIdMapInterface;
-use Drupal\migrate\ProcessPluginBase;
-use Drupal\migrate\Plugin\MigrationInterface;
-use Drupal\migrate\MigrateExecutableInterface;
-use Drupal\migrate\Row;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
 /**
  * Calculates the value of a property based on a previous migration.
  *
@@ -21,156 +10,8 @@
  * @MigrateProcessPlugin(
  *   id = "migration"
  * )
+ *
+ * @deprecated in Drupal 8.3.x and will be removed in Drupal 9.0.x. Use
+ *   \Drupal\migrate\Plugin\migrate\process\MigrationLookup instead.
  */
-class Migration extends ProcessPluginBase implements ContainerFactoryPluginInterface {
-
-  /**
-   * The process plugin manager.
-   *
-   * @var \Drupal\migrate\Plugin\MigratePluginManager
-   */
-  protected $processPluginManager;
-
-  /**
-   * The migration plugin manager.
-   *
-   * @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface
-   */
-  protected $migrationPluginManager;
-
-  /**
-   * The migration to be executed.
-   *
-   * @var \Drupal\migrate\Plugin\MigrationInterface
-   */
-  protected $migration;
-
-  /**
-   * {@inheritdoc}
-   */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, MigrationPluginManagerInterface $migration_plugin_manager, MigratePluginManagerInterface $process_plugin_manager) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
-    $this->migrationPluginManager = $migration_plugin_manager;
-    $this->migration = $migration;
-    $this->processPluginManager = $process_plugin_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
-    return new static(
-      $configuration,
-      $plugin_id,
-      $plugin_definition,
-      $migration,
-      $container->get('plugin.manager.migration'),
-      $container->get('plugin.manager.migrate.process')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
-    $migration_ids = $this->configuration['migration'];
-    if (!is_array($migration_ids)) {
-      $migration_ids = [$migration_ids];
-    }
-    if (!is_array($value)) {
-      $value = [$value];
-    }
-    $this->skipOnEmpty($value);
-    $self = FALSE;
-    /** @var \Drupal\migrate\Plugin\MigrationInterface[] $migrations */
-    $destination_ids = NULL;
-    $source_id_values = [];
-    $migrations = $this->migrationPluginManager->createInstances($migration_ids);
-    foreach ($migrations as $migration_id => $migration) {
-      if ($migration_id == $this->migration->id()) {
-        $self = TRUE;
-      }
-      if (isset($this->configuration['source_ids'][$migration_id])) {
-        $configuration = ['source' => $this->configuration['source_ids'][$migration_id]];
-        $source_id_values[$migration_id] = $this->processPluginManager
-          ->createInstance('get', $configuration, $this->migration)
-          ->transform(NULL, $migrate_executable, $row, $destination_property);
-      }
-      else {
-        $source_id_values[$migration_id] = $value;
-      }
-      // Break out of the loop as soon as a destination ID is found.
-      if ($destination_ids = $migration->getIdMap()->lookupDestinationId($source_id_values[$migration_id])) {
-        break;
-      }
-    }
-
-    if (!$destination_ids && !empty($this->configuration['no_stub'])) {
-      return NULL;
-    }
-
-    if (!$destination_ids && ($self || isset($this->configuration['stub_id']) || count($migrations) == 1)) {
-      // If the lookup didn't succeed, figure out which migration will do the
-      // stubbing.
-      if ($self) {
-        $migration = $this->migration;
-      }
-      elseif (isset($this->configuration['stub_id'])) {
-        $migration = $migrations[$this->configuration['stub_id']];
-      }
-      else {
-        $migration = reset($migrations);
-      }
-      $destination_plugin = $migration->getDestinationPlugin(TRUE);
-      // Only keep the process necessary to produce the destination ID.
-      $process = $migration->getProcess();
-
-      // We already have the source ID values but need to key them for the Row
-      // constructor.
-      $source_ids = $migration->getSourcePlugin()->getIds();
-      $values = [];
-      foreach (array_keys($source_ids) as $index => $source_id) {
-        $values[$source_id] = $source_id_values[$migration->id()][$index];
-      }
-
-      $stub_row = new Row($values + $migration->getSourceConfiguration(), $source_ids, TRUE);
-
-      // Do a normal migration with the stub row.
-      $migrate_executable->processRow($stub_row, $process);
-      $destination_ids = [];
-      try {
-        $destination_ids = $destination_plugin->import($stub_row);
-      }
-      catch (\Exception $e) {
-        $migration->getIdMap()->saveMessage($stub_row->getSourceIdValues(), $e->getMessage());
-      }
-
-      if ($destination_ids) {
-        $migration->getIdMap()->saveIdMapping($stub_row, $destination_ids, MigrateIdMapInterface::STATUS_NEEDS_UPDATE);
-      }
-    }
-    if ($destination_ids) {
-      if (count($destination_ids) == 1) {
-        return reset($destination_ids);
-      }
-      else {
-        return $destination_ids;
-      }
-    }
-  }
-
-  /**
-   * Skips the migration process entirely if the value is FALSE.
-   *
-   * @param mixed $value
-   *   The incoming value to transform.
-   *
-   * @throws \Drupal\migrate\MigrateSkipProcessException
-   */
-  protected function skipOnEmpty(array $value) {
-    if (!array_filter($value)) {
-      throw new MigrateSkipProcessException();
-    }
-  }
-
-}
+class Migration extends MigrationLookup { }
diff --git a/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php b/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php
new file mode 100644
index 0000000..17ac44b
--- /dev/null
+++ b/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php
@@ -0,0 +1,291 @@
+<?php
+
+namespace Drupal\migrate\Plugin\migrate\process;
+
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\migrate\MigrateSkipProcessException;
+use Drupal\migrate\Plugin\MigratePluginManagerInterface;
+use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
+use Drupal\migrate\Plugin\MigrateIdMapInterface;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Plugin\MigrationInterface;
+use Drupal\migrate\MigrateExecutableInterface;
+use Drupal\migrate\Row;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Calculates the value of a property based on a previous migration.
+ *
+ * It is important to maintain relationships among content coming from the
+ * source site, but in most instances the unique identifiers of the content
+ * change in the process of migration. For example, on the source site a given
+ * user account may have an "author" ID of 123, but the Drupal user account
+ * created from it may have a uid of 456. The migration_lookup process maintains
+ * the relationships between source and destination identifiers in map tables,
+ * and this information is leveraged by the migration process plugin.
+ *
+ * Available configuration keys
+ * - migration: An array of migration ids.
+ * - source_ids: (optional) An array keyed by migration ids with values that are
+ *   a list of source properties.
+ * - stub_id: (optional) Identifies which entry in the migration array will be
+ *   used to create any stub entities.
+ *
+ * Examples:
+ *
+ * Consider a node migration, where you want to maintain authorship. If you have
+ * migrated the user accounts in a migration named "users", you would specify
+ * the following:
+ *
+ * @code
+ * process:
+ *   uid:
+ *     plugin: migration_lookup
+ *     migration: users
+ *     source: author
+ * @endcode
+ *
+ * This takes the value of the author property in the source data, and looks it
+ * up in the map table associated with the users migration, returning the
+ * resulting user ID and assigning it to the destination uid property.
+ *
+ * The value of migration can be a list of migration ids. When using multiple
+ * migrations it is possible each use different source identifiers. In this
+ * case one can use source_ids which is an array keyed by the migration ids
+ * and the value is a list of source properties with the same features as normal
+ * source (see the get plugin for more on this).
+ *
+ * @code
+ * process:
+ *   uid:
+ *   plugin: migration_lookup
+ *   migration:
+ *     - users
+ *     - members
+ *   source_ids:
+ *     users:
+ *       - author
+ *     members:
+ *       - author
+ * @endcode
+ *
+ * If the migration_lookup does not find the source ID in the migration map it
+ * will create a stub entity for the relationship to use. This stub is generated
+ * by the migration provided. In the case of multiple migrations the first value
+ * of migration list will be used, but you can select the migration you wish to
+ * use to create the stub:
+ *
+ * @code
+ * process:
+ *   uid:
+ *     plugin: migration_lookup
+ *     migration:
+ *       - users
+ *       - members
+ *     source_ids:
+ *       users:
+ *         - author
+ *       members:
+ *         - author
+ *     stub_id: members
+ * @endcode
+ *
+ * Here, the value of stub_id selects the members migration to create any stub
+ * entities, overriding the default of the users migration.
+ *
+ * To prevent the creation of a stub entity when no relationship is found in the
+ * migration map, use no_stub. It can be set to any non-empty value:
+ *
+ * @code
+ * process:
+ *   uid:
+ *   plugin: migration_lookup
+ *   migration: users
+ *   no_stub: true
+ *   source: author
+ * @endcode
+ *
+ * Scenario:
+ *   - field_drupal6_pages is a drupal 6 node reference field.
+ *   - field_drupal8_pages is a drupal 8 entity reference field.
+ *
+ * @code
+ * field_drupal8_pages:
+ *   plugin: migration_lookup
+ *   migration: ya_node_page
+ *   source: field_drupal6_pages
+ * @endcode
+ *
+ * Scenario:
+ *   - field_drupal7_pages is a drupal 7 entity reference field.
+ *   - field_drupal8_pages is a drupal 8 entity reference field.
+ *
+ * @code
+ * field_drupal8_pages:
+ *   plugin: iterator
+ *   source: field_drupal7_pages
+ *   process:
+ *     target_id:
+ *       plugin: migration_lookup
+ *       migration: ya_node_page
+ *       source: target_id
+ * @endcode
+ *
+ * @see \Drupal\migrate\Plugin\MigrateProcessInterface
+ *
+ * @MigrateProcessPlugin(
+ *   id = "migration_lookup"
+ * )
+ */
+class MigrationLookup extends ProcessPluginBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The process plugin manager.
+   *
+   * @var \Drupal\migrate\Plugin\MigratePluginManager
+   */
+  protected $processPluginManager;
+
+  /**
+   * The migration plugin manager.
+   *
+   * @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface
+   */
+  protected $migrationPluginManager;
+
+  /**
+   * The migration to be executed.
+   *
+   * @var \Drupal\migrate\Plugin\MigrationInterface
+   */
+  protected $migration;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, MigrationPluginManagerInterface $migration_plugin_manager, MigratePluginManagerInterface $process_plugin_manager) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->migrationPluginManager = $migration_plugin_manager;
+    $this->migration = $migration;
+    $this->processPluginManager = $process_plugin_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $container->get('plugin.manager.migration'),
+      $container->get('plugin.manager.migrate.process')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
+    $migration_ids = $this->configuration['migration'];
+    if (!is_array($migration_ids)) {
+      $migration_ids = [$migration_ids];
+    }
+    if (!is_array($value)) {
+      $value = [$value];
+    }
+    $this->skipOnEmpty($value);
+    $self = FALSE;
+    /** @var \Drupal\migrate\Plugin\MigrationInterface[] $migrations */
+    $destination_ids = NULL;
+    $source_id_values = [];
+    $migrations = $this->migrationPluginManager->createInstances($migration_ids);
+    foreach ($migrations as $migration_id => $migration) {
+      if ($migration_id == $this->migration->id()) {
+        $self = TRUE;
+      }
+      if (isset($this->configuration['source_ids'][$migration_id])) {
+        $configuration = ['source' => $this->configuration['source_ids'][$migration_id]];
+        $source_id_values[$migration_id] = $this->processPluginManager
+          ->createInstance('get', $configuration, $this->migration)
+          ->transform(NULL, $migrate_executable, $row, $destination_property);
+      }
+      else {
+        $source_id_values[$migration_id] = $value;
+      }
+      // Break out of the loop as soon as a destination ID is found.
+      if ($destination_ids = $migration->getIdMap()->lookupDestinationId($source_id_values[$migration_id])) {
+        break;
+      }
+    }
+
+    if (!$destination_ids && !empty($this->configuration['no_stub'])) {
+      return NULL;
+    }
+
+    if (!$destination_ids && ($self || isset($this->configuration['stub_id']) || count($migrations) == 1)) {
+      // If the lookup didn't succeed, figure out which migration will do the
+      // stubbing.
+      if ($self) {
+        $migration = $this->migration;
+      }
+      elseif (isset($this->configuration['stub_id'])) {
+        $migration = $migrations[$this->configuration['stub_id']];
+      }
+      else {
+        $migration = reset($migrations);
+      }
+      $destination_plugin = $migration->getDestinationPlugin(TRUE);
+      // Only keep the process necessary to produce the destination ID.
+      $process = $migration->getProcess();
+
+      // We already have the source ID values but need to key them for the Row
+      // constructor.
+      $source_ids = $migration->getSourcePlugin()->getIds();
+      $values = [];
+      foreach (array_keys($source_ids) as $index => $source_id) {
+        $values[$source_id] = $source_id_values[$migration->id()][$index];
+      }
+
+      $stub_row = new Row($values + $migration->getSourceConfiguration(), $source_ids, TRUE);
+
+      // Do a normal migration with the stub row.
+      $migrate_executable->processRow($stub_row, $process);
+      $destination_ids = [];
+      try {
+        $destination_ids = $destination_plugin->import($stub_row);
+      }
+      catch (\Exception $e) {
+        $migration->getIdMap()->saveMessage($stub_row->getSourceIdValues(), $e->getMessage());
+      }
+
+      if ($destination_ids) {
+        $migration->getIdMap()->saveIdMapping($stub_row, $destination_ids, MigrateIdMapInterface::STATUS_NEEDS_UPDATE);
+      }
+    }
+    if ($destination_ids) {
+      if (count($destination_ids) == 1) {
+        return reset($destination_ids);
+      }
+      else {
+        return $destination_ids;
+      }
+    }
+  }
+
+  /**
+   * Skips the migration process entirely if the value is FALSE.
+   *
+   * @param mixed $value
+   *   The incoming value to transform.
+   *
+   * @throws \Drupal\migrate\MigrateSkipProcessException
+   */
+  protected function skipOnEmpty(array $value) {
+    if (!array_filter($value)) {
+      throw new MigrateSkipProcessException();
+    }
+  }
+
+}
diff --git a/core/modules/migrate/tests/modules/migrate_external_translated_test/migrations/migrate.migration.external_translated_test_node_translation.yml b/core/modules/migrate/tests/modules/migrate_external_translated_test/migrations/migrate.migration.external_translated_test_node_translation.yml
index ff29084..0363aa2 100644
--- a/core/modules/migrate/tests/modules/migrate_external_translated_test/migrations/migrate.migration.external_translated_test_node_translation.yml
+++ b/core/modules/migrate/tests/modules/migrate_external_translated_test/migrations/migrate.migration.external_translated_test_node_translation.yml
@@ -7,7 +7,7 @@ source:
     type: external_test
 process:
   nid:
-    plugin: migration
+    plugin: migration_lookup
     source: name
     migration: external_translated_test_node
   type: constants/type
diff --git a/core/modules/migrate/tests/src/Unit/process/MigrationTest.php b/core/modules/migrate/tests/src/Unit/process/MigrationLookupTest.php
similarity index 90%
rename from core/modules/migrate/tests/src/Unit/process/MigrationTest.php
rename to core/modules/migrate/tests/src/Unit/process/MigrationLookupTest.php
index b62c1f9..d768443 100644
--- a/core/modules/migrate/tests/src/Unit/process/MigrationTest.php
+++ b/core/modules/migrate/tests/src/Unit/process/MigrationLookupTest.php
@@ -4,7 +4,7 @@
 
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\migrate\Plugin\MigrationInterface;
-use Drupal\migrate\Plugin\migrate\process\Migration;
+use Drupal\migrate\Plugin\migrate\process\MigrationLookup;
 use Drupal\migrate\Plugin\MigrateDestinationInterface;
 use Drupal\migrate\Plugin\MigrateIdMapInterface;
 use Drupal\migrate\Plugin\MigratePluginManager;
@@ -13,10 +13,10 @@
 use Prophecy\Argument;
 
 /**
- * @coversDefaultClass \Drupal\migrate\Plugin\migrate\process\Migration
+ * @coversDefaultClass \Drupal\migrate\Plugin\migrate\process\MigrationLookup
  * @group migrate
  */
-class MigrationTest extends MigrateProcessTestCase {
+class MigrationLookupTest extends MigrateProcessTestCase {
 
   /**
    * @covers ::transform
@@ -43,7 +43,7 @@ public function testTransformWithStubSkipping() {
     $migration_plugin->id()->willReturn('actual_migration');
     $destination_migration->getDestinationPlugin(TRUE)->shouldNotBeCalled();
 
-    $migration = new Migration($configuration, '', [], $migration_plugin->reveal(), $migration_plugin_manager->reveal(), $process_plugin_manager->reveal());
+    $migration = new MigrationLookup($configuration, '', [], $migration_plugin->reveal(), $migration_plugin_manager->reveal(), $process_plugin_manager->reveal());
     $result = $migration->transform(1, $this->migrateExecutable, $this->row, '');
     $this->assertNull($result);
   }
@@ -82,7 +82,7 @@ public function testTransformWithStubbing() {
     $destination_plugin->import(Argument::any())->willReturn([2]);
     $destination_migration->getDestinationPlugin(TRUE)->willReturn($destination_plugin->reveal());
 
-    $migration = new Migration($configuration, '', [], $migration_plugin->reveal(), $migration_plugin_manager->reveal(), $process_plugin_manager->reveal());
+    $migration = new MigrationLookup($configuration, '', [], $migration_plugin->reveal(), $migration_plugin_manager->reveal(), $process_plugin_manager->reveal());
     $result = $migration->transform(1, $this->migrateExecutable, $this->row, '');
     $this->assertEquals(2, $result);
   }
@@ -101,7 +101,7 @@ public function testSkipOnEmpty() {
       'migration' => 'foobaz',
     ];
     $migration_plugin->id()->willReturn(uniqid());
-    $migration = new Migration($configuration, 'migration', [], $migration_plugin->reveal(), $migration_plugin_manager->reveal(), $process_plugin_manager->reveal());
+    $migration = new MigrationLookup($configuration, 'migration_lookup', [], $migration_plugin->reveal(), $migration_plugin_manager->reveal(), $process_plugin_manager->reveal());
     $migration->transform(0, $this->migrateExecutable, $this->row, 'foo');
   }
 
@@ -141,7 +141,7 @@ public function testSuccessfulLookup($source_id_values, $destination_id_values,
       ->loadMultiple(['foobaz'])
       ->willReturn([$migration_plugin->reveal()]);
 
-    $migration = new Migration($configuration, 'migration', [], $migration_plugin->reveal(), $migration_plugin_manager->reveal(), $process_plugin_manager->reveal());
+    $migration = new MigrationLookup($configuration, 'migration_lookup', [], $migration_plugin->reveal(), $migration_plugin_manager->reveal(), $process_plugin_manager->reveal());
     $this->assertSame($expected_value, $migration->transform($source_value, $this->migrateExecutable, $this->row, 'foo'));
   }
 
diff --git a/core/modules/node/migration_templates/d6_node.yml b/core/modules/node/migration_templates/d6_node.yml
index 4e19bb4..56d0459 100644
--- a/core/modules/node/migration_templates/d6_node.yml
+++ b/core/modules/node/migration_templates/d6_node.yml
@@ -25,7 +25,7 @@ process:
   promote: promote
   sticky: sticky
   'body/format':
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_filter_format
     source: format
   'body/value': body
diff --git a/core/modules/node/migration_templates/d6_node_revision.yml b/core/modules/node/migration_templates/d6_node_revision.yml
index 046e9bb..f4ff301 100644
--- a/core/modules/node/migration_templates/d6_node_revision.yml
+++ b/core/modules/node/migration_templates/d6_node_revision.yml
@@ -22,7 +22,7 @@ process:
   promote: promote
   sticky: sticky
   'body/format':
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_filter_format
     source: format
   'body/value': body
diff --git a/core/modules/node/migration_templates/d6_node_translation.yml b/core/modules/node/migration_templates/d6_node_translation.yml
index 3b923d1..3eb06e8 100644
--- a/core/modules/node/migration_templates/d6_node_translation.yml
+++ b/core/modules/node/migration_templates/d6_node_translation.yml
@@ -23,7 +23,7 @@ process:
   promote: promote
   sticky: sticky
   'body/format':
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_filter_format
     source: format
   'body/value': body
diff --git a/core/modules/path/migration_templates/d6_url_alias.yml b/core/modules/path/migration_templates/d6_url_alias.yml
index 968b1e6..fcf2036 100644
--- a/core/modules/path/migration_templates/d6_url_alias.yml
+++ b/core/modules/path/migration_templates/d6_url_alias.yml
@@ -30,7 +30,7 @@ process:
       index:
         - 1
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_node_translation
 destination:
   plugin: url_alias
diff --git a/core/modules/path/migration_templates/d7_url_alias.yml b/core/modules/path/migration_templates/d7_url_alias.yml
index 713a346..dffaf46 100644
--- a/core/modules/path/migration_templates/d7_url_alias.yml
+++ b/core/modules/path/migration_templates/d7_url_alias.yml
@@ -28,7 +28,7 @@ process:
       index:
         - 1
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d7_node_translation
 destination:
   plugin: url_alias
diff --git a/core/modules/shortcut/migration_templates/d7_shortcut.yml b/core/modules/shortcut/migration_templates/d7_shortcut.yml
index da3d894..dac9354 100644
--- a/core/modules/shortcut/migration_templates/d7_shortcut.yml
+++ b/core/modules/shortcut/migration_templates/d7_shortcut.yml
@@ -8,7 +8,7 @@ source:
     uri_scheme: 'internal:/'
 process:
   shortcut_set:
-     plugin: migration
+     plugin: migration_lookup
      migration: d7_shortcut_set
      source: menu_name
   title: link_title
diff --git a/core/modules/shortcut/migration_templates/d7_shortcut_set_users.yml b/core/modules/shortcut/migration_templates/d7_shortcut_set_users.yml
index a93c4bb..d0eb219 100644
--- a/core/modules/shortcut/migration_templates/d7_shortcut_set_users.yml
+++ b/core/modules/shortcut/migration_templates/d7_shortcut_set_users.yml
@@ -7,14 +7,14 @@ source:
 process:
   uid:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d7_user
       source: uid
     -
       plugin: skip_on_empty
       method: row
   set_name:
-    plugin: migration
+    plugin: migration_lookup
     migration: d7_shortcut_set
     source: set_name
 destination:
diff --git a/core/modules/taxonomy/migration_templates/d6_taxonomy_term.yml b/core/modules/taxonomy/migration_templates/d6_taxonomy_term.yml
index e5630fc..e3c3e3d 100644
--- a/core/modules/taxonomy/migration_templates/d6_taxonomy_term.yml
+++ b/core/modules/taxonomy/migration_templates/d6_taxonomy_term.yml
@@ -9,7 +9,7 @@ process:
   # the tid field to allow incremental migrations.
   tid: tid
   vid:
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_taxonomy_vocabulary
     source: vid
   name: name
@@ -22,7 +22,7 @@ process:
       method: process
       source: parent
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_taxonomy_term
   parent:
     plugin: default_value
diff --git a/core/modules/taxonomy/migration_templates/d6_term_node.yml b/core/modules/taxonomy/migration_templates/d6_term_node.yml
index 63aec85..846334d 100644
--- a/core/modules/taxonomy/migration_templates/d6_term_node.yml
+++ b/core/modules/taxonomy/migration_templates/d6_term_node.yml
@@ -8,7 +8,7 @@ source:
 process:
   nid:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_node
       source: nid
     -
diff --git a/core/modules/taxonomy/migration_templates/d6_term_node_revision.yml b/core/modules/taxonomy/migration_templates/d6_term_node_revision.yml
index cf1c682..91c8362 100644
--- a/core/modules/taxonomy/migration_templates/d6_term_node_revision.yml
+++ b/core/modules/taxonomy/migration_templates/d6_term_node_revision.yml
@@ -8,7 +8,7 @@ source:
 process:
   vid:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_node
       source: vid
     -
diff --git a/core/modules/taxonomy/migration_templates/d6_vocabulary_entity_display.yml b/core/modules/taxonomy/migration_templates/d6_vocabulary_entity_display.yml
index e8d04c0..3c52a2f 100644
--- a/core/modules/taxonomy/migration_templates/d6_vocabulary_entity_display.yml
+++ b/core/modules/taxonomy/migration_templates/d6_vocabulary_entity_display.yml
@@ -17,7 +17,7 @@ process:
   options: 'constants/options'
   bundle: type
   field_name:
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_taxonomy_vocabulary
     source: vid
 destination:
diff --git a/core/modules/taxonomy/migration_templates/d6_vocabulary_entity_form_display.yml b/core/modules/taxonomy/migration_templates/d6_vocabulary_entity_form_display.yml
index 2608877..160f68c 100644
--- a/core/modules/taxonomy/migration_templates/d6_vocabulary_entity_form_display.yml
+++ b/core/modules/taxonomy/migration_templates/d6_vocabulary_entity_form_display.yml
@@ -21,7 +21,7 @@ process:
   options/weight: 'constants/options/weight'
   bundle: type
   field_name:
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_taxonomy_vocabulary
     source: vid
 destination:
diff --git a/core/modules/taxonomy/migration_templates/d6_vocabulary_field.yml b/core/modules/taxonomy/migration_templates/d6_vocabulary_field.yml
index 0e1a487..082386f 100644
--- a/core/modules/taxonomy/migration_templates/d6_vocabulary_field.yml
+++ b/core/modules/taxonomy/migration_templates/d6_vocabulary_field.yml
@@ -13,7 +13,7 @@ process:
   type: 'constants/type'
   field_name:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_taxonomy_vocabulary
       source: vid
     -
diff --git a/core/modules/taxonomy/migration_templates/d6_vocabulary_field_instance.yml b/core/modules/taxonomy/migration_templates/d6_vocabulary_field_instance.yml
index a7bbbbb..a3afd9b9 100644
--- a/core/modules/taxonomy/migration_templates/d6_vocabulary_field_instance.yml
+++ b/core/modules/taxonomy/migration_templates/d6_vocabulary_field_instance.yml
@@ -13,7 +13,7 @@ process:
   bundle: type
   field_name:
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d6_taxonomy_vocabulary
       source: vid
     -
diff --git a/core/modules/taxonomy/migration_templates/d7_taxonomy_term.yml b/core/modules/taxonomy/migration_templates/d7_taxonomy_term.yml
index af85180..99004df 100644
--- a/core/modules/taxonomy/migration_templates/d7_taxonomy_term.yml
+++ b/core/modules/taxonomy/migration_templates/d7_taxonomy_term.yml
@@ -10,7 +10,7 @@ process:
   # the tid field to allow incremental migrations.
   tid: tid
   vid:
-    plugin: migration
+    plugin: migration_lookup
     migration: d7_taxonomy_vocabulary
     source: vid
   name: name
@@ -24,7 +24,7 @@ process:
       method: process
       source: parent
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d7_taxonomy_term
   parent:
     plugin: default_value
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_term_stub_test/migrations/taxonomy_term_stub_test.yml b/core/modules/taxonomy/tests/modules/taxonomy_term_stub_test/migrations/taxonomy_term_stub_test.yml
index ad56fff..4c3cd86 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_term_stub_test/migrations/taxonomy_term_stub_test.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_term_stub_test/migrations/taxonomy_term_stub_test.yml
@@ -19,7 +19,7 @@ process:
   name: name
   weight: weight
   parent:
-    plugin: migration
+    plugin: migration_lookup
     migration: taxonomy_term_stub_test
     source: parent
 destination:
diff --git a/core/modules/user/migration_templates/d6_user.yml b/core/modules/user/migration_templates/d6_user.yml
index c82c657..d58607b 100644
--- a/core/modules/user/migration_templates/d6_user.yml
+++ b/core/modules/user/migration_templates/d6_user.yml
@@ -32,11 +32,11 @@ process:
     fallback_to_site_default: true
   init: init
   roles:
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_user_role
     source: roles
   user_picture:
-    plugin: migration
+    plugin: migration_lookup
     migration: d6_user_picture_file
     source: uid
     no_stub: true
diff --git a/core/modules/user/migration_templates/d7_user.yml b/core/modules/user/migration_templates/d7_user.yml
index d68e297..ae52384 100644
--- a/core/modules/user/migration_templates/d7_user.yml
+++ b/core/modules/user/migration_templates/d7_user.yml
@@ -31,7 +31,7 @@ process:
     fallback_to_site_default: true
   init: init
   roles:
-    plugin: migration
+    plugin: migration_lookup
     migration: d7_user_role
     source: roles
   user_picture:
@@ -40,7 +40,7 @@ process:
       source: picture
       default_value: null
     -
-      plugin: migration
+      plugin: migration_lookup
       migration: d7_file
 destination:
   plugin: entity:user
