diff --git a/config/schema/migrate_plus.schema.yml b/config/schema/migrate_plus.schema.yml
index a2c682d446960d25c96734208251d7ff3984b10e..87f59a3bbedc117693b847b933d90f9106a78d35 100644
--- a/config/schema/migrate_plus.schema.yml
+++ b/config/schema/migrate_plus.schema.yml
@@ -13,6 +13,9 @@ migrate_plus.migration.*:
       sequence:
         type: string
         label: 'Tag'
+    migration_group:
+      type: string
+      label: 'Group'
     label:
       type: label
       label: 'Label'
@@ -67,10 +70,3 @@ migrate_plus.migration_group.*:
     shared_configuration:
       type: ignore
       label: 'Shared migration configuration'
-migrate_plus.migration.*.third_party.migrate_plus:
-  type: mapping
-  label: 'Group'
-  mapping:
-    migration_group:
-      type: string
-      label: 'Group'
diff --git a/migrate_example/config/install/migrate_plus.migration.beer_comment.yml b/migrate_example/config/install/migrate_plus.migration.beer_comment.yml
index 20962df7843c1e419ef14f0f1c4bb6f9d7a0371a..991c59b1305beee7016f5728f77a4382a41e8b42 100644
--- a/migrate_example/config/install/migrate_plus.migration.beer_comment.yml
+++ b/migrate_example/config/install/migrate_plus.migration.beer_comment.yml
@@ -1,12 +1,9 @@
 # Migration configuration for beer comments. No new concepts here.
 id: beer_comment
 label: Comments on beers
-third_party_settings:
-  migrate_plus:
-    migration_group: beer
+migration_group: beer
 source:
   plugin: beer_comment
-  key: default
 destination:
   plugin: entity:comment
 process:
diff --git a/migrate_example/config/install/migrate_plus.migration.beer_node.yml b/migrate_example/config/install/migrate_plus.migration.beer_node.yml
index 19b52257be36b9041d3d266bb20b6f306c4ec215..b84832237524c88fde7b32fb8688eeb1a74adae9 100644
--- a/migrate_example/config/install/migrate_plus.migration.beer_node.yml
+++ b/migrate_example/config/install/migrate_plus.migration.beer_node.yml
@@ -1,12 +1,9 @@
 # Migration configuration for beer content.
 id: beer_node
 label: Beers of the world
-third_party_settings:
-  migrate_plus:
-    migration_group: beer
+migration_group: beer
 source:
   plugin: beer_node
-  key: default
 destination:
   plugin: entity:node
 process:
diff --git a/migrate_example/config/install/migrate_plus.migration.beer_term.yml b/migrate_example/config/install/migrate_plus.migration.beer_term.yml
index b0ee91ace3f87c7f963f93ba6376e0f19724a5a8..32573fa9e8a07ae9aa6a304d4172c2d97eed8af8 100644
--- a/migrate_example/config/install/migrate_plus.migration.beer_term.yml
+++ b/migrate_example/config/install/migrate_plus.migration.beer_term.yml
@@ -1,4 +1,4 @@
-# A "migration" is, in technical terms, a configuration entity which describes
+# A "migration" is, in technical terms, a plugin whose configuration describes
 # how to read source data, process it (generally by mapping source fields to
 # destination fields), and write it to Drupal.
 
@@ -8,17 +8,9 @@ id: beer_term
 # A human-friendly description of the migration.
 label: Migrate style categories from the source database to taxonomy terms
 
-# This section contains configuration added by modules other than the primary
-# module defining the configuration entity. The 'migrate.migration.' at the
-# beginning of the file name indicates that the migrate module defines the
-# migration configuration entity type. The migrate_plus module extends that
-# entity type with the group concept, thus the settings it provides fall under
-# 'third_party_settings:' and 'migrate_plus:'.
-third_party_settings:
-  migrate_plus:
-    # The machine name of the group containing this migration (which contains
-    # shared configuration to be merged with our own configuration here).
-    migration_group: beer
+# The machine name of the group containing this migration (which contains shared
+# configuration to be merged with our own configuration here).
+migration_group: beer
 
 # Every migration must have a source plugin, which controls the delivery of our
 # source data. In this case, our source plugin has the name "beer_term", which
@@ -26,7 +18,6 @@ third_party_settings:
 # src/Plugin/migrate/source/BeerTerm.php.
 source:
   plugin: beer_term
-  key: default
 
 # Every migration must also have a destination plugin, which handles writing
 # the migrated data in the appropriate form for that particular kind of data.
diff --git a/migrate_example/config/install/migrate_plus.migration.beer_user.yml b/migrate_example/config/install/migrate_plus.migration.beer_user.yml
index fcbb4702831f5160c1310270fd429d1f1c5400b8..71d07e6d2f7a51f59adb1d1412cb0b61968780e8 100644
--- a/migrate_example/config/install/migrate_plus.migration.beer_user.yml
+++ b/migrate_example/config/install/migrate_plus.migration.beer_user.yml
@@ -3,12 +3,9 @@
 # repeat that here.
 id: beer_user
 label: Beer Drinkers of the world
-third_party_settings:
-  migrate_plus:
-    migration_group: beer
+migration_group: beer
 source:
   plugin: beer_user
-  key: default
 destination:
   plugin: entity:user
 process:
diff --git a/migrate_plus.module b/migrate_plus.module
index 3c9a6f732fdd567846a318e2641a2a183dc4a774..c6a11c976efb84c7fb175d9a6e78ce48c4355a3f 100644
--- a/migrate_plus.module
+++ b/migrate_plus.module
@@ -16,23 +16,12 @@ use Drupal\migrate_plus\Event\MigratePrepareRowEvent;
  * Implements hook_migration_plugins_alter().
  */
 function migrate_tools_migration_plugins_alter(array &$migrations) {
-  // @todo: Implement group merging here.
-}
-
-/**
- * Implements hook_ENTITY_TYPE_load().
- */
-function migrate_plus_migration_load($migrations) {
-  // @todo: Replace with hook_migration_plugins()
-  return;
-  /** @var MigrationInterface $migration */
-  foreach ($migrations as $migration) {
-    // If we are pointing to a valid group, merge its properties into ours.
-    $migration_group = $migration->getThirdPartySetting('migrate_plus', 'migration_group');
-    if (empty($migration_group)) {
+  /** @var \Drupal\migrate\Plugin\MigrationInterface $migration */
+  foreach ($migrations as $id => $migration) {
+    if (empty($migration['migration_group'])) {
       continue;
     }
-    $group = MigrationGroup::load($migration_group);
+    $group = MigrationGroup::load($migration['migration_group']);
     if (empty($group)) {
       continue;
     }
@@ -41,21 +30,20 @@ function migrate_plus_migration_load($migrations) {
       continue;
     }
     foreach ($shared_configuration as $key => $group_value) {
-      $migration_value = $migration->get($key);
-      // Where both the migration and the group provide arrays,
-      // replace recursively (so each key collision is resolved in favor
-      // of the migration).
+      $migration_value = $migration[$key];
+      // Where both the migration and the group provide arrays, replace
+      // recursively (so each key collision is resolved in favor of the
+      // migration).
       if (is_array($migration_value) && is_array($group_value)) {
         $merged_values = array_replace_recursive($group_value, $migration_value);
-        $migration->set($key, $merged_values);
+        $migrations[$id][$key] = $merged_values;
       }
-      // Where the group provides a value the migration doesn't, use
-      // the group value.
+      // Where the group provides a value the migration doesn't, use the group
+      // value.
       elseif (is_null($migration_value)) {
-        $migration->set($key, $group_value);
+        $migrations[$id][$key] = $group_value;
       }
-      // Otherwise, the existing migration value overrides the group
-      // value.
+      // Otherwise, the existing migration value overrides the group value.
     }
   }
 }