diff --git bp-core/bp-core-update.php bp-core/bp-core-update.php
index cc9dd70..940d0dc 100644
--- bp-core/bp-core-update.php
+++ bp-core/bp-core-update.php
@@ -365,40 +365,8 @@ function bp_update_to_2_0() {
 		// Maybe install the signups table
 		bp_core_maybe_install_signups();
 
-		$signups = get_users( array(
-			'fields'       => 'all_with_meta',
-			'meta_key'     => 'activation_key',
-			'meta_compare' => 'EXISTS',
-		) );
-
-		if ( empty( $signups ) ) {
-			return;
-		}
-
-		foreach ( $signups as $signup ) {
-			$meta = array();
-
-			if ( bp_is_active( 'xprofile' ) ) {
-				$meta['field_1'] = $signup->display_name;
-			}
-
-			$meta['password'] = $signup->user_pass;
-
-			$user_login = preg_replace( '/\s+/', '', sanitize_user( $signup->user_login, true ) );
-			$user_email = sanitize_email( $signup->user_email );
-
-			BP_Signup::add( array(
-				'user_login'     => $user_login,
-				'user_email'     => $user_email,
-				'registered'     => $signup->user_registered,
-				'activation_key' => $signup->activation_key,
-				'meta'           => $meta
-			) );
-
-			// Deleting these options will remove signups from users count
-			delete_user_option( $signup->ID, 'capabilities' );
-			delete_user_option( $signup->ID, 'user_level'   );
-		}
+		// Run the migration script
+		bp_members_migrate_signups();
 	}
 
 	/** Add BP options to the options table ***********************************/
diff --git bp-members/bp-members-functions.php bp-members/bp-members-functions.php
index 6dbe403..0f3e9d3 100644
--- bp-members/bp-members-functions.php
+++ bp-members/bp-members-functions.php
@@ -1637,6 +1637,87 @@ function bp_core_activate_signup( $key ) {
 	return $user_id;
 }
 
+/**
+ * Migrate signups from pre-2.0 configuration to wp_signups.
+ *
+ * @since BuddyPress (2.0.1)
+ */
+function bp_members_migrate_signups() {
+	global $wpdb;
+
+	$status_2_ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->users} WHERE user_status = '2'" );
+
+	if ( ! empty( $status_2_ids ) ) {
+		$signups = get_users( array(
+			'fields'  => array(
+				'ID',
+				'user_login',
+				'user_pass',
+				'user_registered',
+				'user_email',
+				'display_name',
+			),
+			'include' => $status_2_ids,
+		) );
+
+		// Fetch activation keys separately, to avoid the all_with_meta
+		// overhead
+		$status_2_ids_sql = implode( ',', $status_2_ids );
+		$ak_data = $wpdb->get_results( "SELECT user_id, meta_value FROM {$wpdb->usermeta} WHERE meta_key = 'activation_key' AND user_id IN ({$status_2_ids_sql})" );
+
+		// Rekey
+		$activation_keys = array();
+		foreach ( $ak_data as $ak_datum ) {
+			$activation_keys[ intval( $ak_datum->user_id ) ] = $ak_datum->meta_value;
+		}
+
+		unset( $status_2_ids_sql, $status_2_ids, $ak_data );
+
+		// Merge
+		foreach ( $signups as &$signup ) {
+			if ( isset( $activation_keys[ $signup->ID ] ) ) {
+				$signup->activation_key = $activation_keys[ $signup->ID ];
+			}
+		}
+
+		// Reset the signup var as we're using it to process the migration
+		unset( $signup );
+
+	} else {
+		return;
+	}
+
+	foreach ( $signups as $signup ) {
+		$meta = array();
+
+		// Rebuild the activation key, if missing
+		if ( empty( $signup->activation_key ) ) {
+			$signup->activation_key = wp_hash( $signup->ID );
+		}
+
+		if ( bp_is_active( 'xprofile' ) ) {
+			$meta['field_1'] = $signup->display_name;
+		}
+
+		$meta['password'] = $signup->user_pass;
+
+		$user_login = preg_replace( '/\s+/', '', sanitize_user( $signup->user_login, true ) );
+		$user_email = sanitize_email( $signup->user_email );
+
+		BP_Signup::add( array(
+			'user_login'     => $user_login,
+			'user_email'     => $user_email,
+			'registered'     => $signup->user_registered,
+			'activation_key' => $signup->activation_key,
+			'meta'           => $meta
+		) );
+
+		// Deleting these options will remove signups from users count
+		delete_user_option( $signup->ID, 'capabilities' );
+		delete_user_option( $signup->ID, 'user_level'   );
+	}
+}
+
 function bp_core_new_user_activity( $user ) {
 	if ( empty( $user ) || !bp_is_active( 'activity' ) )
 		return false;
diff --git tests/testcases/members/functions.php tests/testcases/members/functions.php
index 4444ccc..c79e3f4 100644
--- tests/testcases/members/functions.php
+++ tests/testcases/members/functions.php
@@ -279,4 +279,95 @@ class BP_Tests_Members_Functions extends BP_UnitTestCase {
 
 		$this->assertSame( $expected, bp_core_get_user_displaynames( array( $u1, $u2, ) ) );
 	}
+
+	/**
+	 * @group bp_members_migrate_signups
+	 */
+	public function test_bp_members_migrate_signups_standard() {
+		$u = $this->create_user();
+		$u_obj = new WP_User( $u );
+
+		// Fake an old-style registration
+		$key = wp_hash( $u_obj->ID );
+		update_user_meta( $u, 'activation_key', $key );
+
+		global $wpdb;
+		$wpdb->update(
+			$wpdb->users,
+			array( 'user_status' => '2', ),
+			array( 'ID' => $u, ),
+			array( '%d', ),
+			array( '%d', )
+		);
+		clean_user_cache( $u );
+
+		bp_members_migrate_signups();
+
+		$found = BP_Signup::get();
+
+		// Use email address as a sanity check
+		$found_email = isset( $found['signups'][0]->user_email ) ? $found['signups'][0]->user_email : '';
+		$this->assertSame( $u_obj->user_email, $found_email );
+
+		// Check that activation keys match
+		$found_key = isset( $found['signups'][0]->activation_key ) ? $found['signups'][0]->activation_key : '';
+		$this->assertSame( $key, $found_key );
+	}
+
+	/**
+	 * @group bp_members_migrate_signups
+	 */
+	public function test_bp_members_migrate_signups_activation_key_but_user_status_0() {
+		$u = $this->create_user();
+		$u_obj = new WP_User( $u );
+
+		// Fake an old-style registration
+		$key = wp_hash( $u_obj->ID );
+		update_user_meta( $u, 'activation_key', $key );
+
+		// ...but ensure that user_status is 0. This mimics the
+		// behavior of certain plugins that disrupt the BP registration
+		// flow
+		global $wpdb;
+		$wpdb->update(
+			$wpdb->users,
+			array( 'user_status' => '0', ),
+			array( 'ID' => $u, ),
+			array( '%d', ),
+			array( '%d', )
+		);
+		clean_user_cache( $u );
+
+		bp_members_migrate_signups();
+
+		// No migrations should have taken place
+		$found = BP_Signup::get();
+		$this->assertEmpty( $found['total'] );
+	}
+
+	/**
+	 * @group bp_members_migrate_signups
+	 */
+	public function test_bp_members_migrate_signups_no_activation_key_but_user_status_2() {
+		$u = $this->create_user();
+		$u_obj = new WP_User( $u );
+
+		// Fake an old-style registration but without an activation key
+		global $wpdb;
+		$wpdb->update(
+			$wpdb->users,
+			array( 'user_status' => '2', ),
+			array( 'ID' => $u, ),
+			array( '%d', ),
+			array( '%d', )
+		);
+		clean_user_cache( $u );
+
+		bp_members_migrate_signups();
+
+		// Use email address as a sanity check
+		$found = BP_Signup::get();
+		$found_email = isset( $found['signups'][0]->user_email ) ? $found['signups'][0]->user_email : '';
+		$this->assertSame( $u_obj->user_email, $found_email );
+	}
 }
