diff --git src/bp-groups/bp-groups-cache.php src/bp-groups/bp-groups-cache.php
index 32d1ade..819fbc4 100644
--- src/bp-groups/bp-groups-cache.php
+++ src/bp-groups/bp-groups-cache.php
@@ -226,6 +226,32 @@ function groups_clear_group_type_cache( $group_id = 0 ) {
 }
 add_action( 'groups_delete_group', 'groups_clear_group_type_cache' );
 
+/**
+ * Clear caches on membership save.
+ *
+ * @since 2.6.0
+ */
+function bp_groups_clear_user_group_cache_on_membership_save( BP_Groups_Member $member ) {
+	wp_cache_delete( $member->user_id, 'bp_groups_memberships_for_user' );
+	wp_cache_delete( $member->id, 'bp_groups_memberships' );
+}
+add_action( 'groups_member_before_save', 'bp_groups_clear_user_group_cache_on_membership_save' );
+add_action( 'groups_member_before_remove', 'bp_groups_clear_user_group_cache_on_membership_save' );
+
+/**
+ * Clear group memberships cache on miscellaneous actions not covered by the 'after_save' hook.
+ *
+ * @since 2.6.0
+ */
+function bp_groups_clear_user_group_cache_on_other_events( $user_id, $group_id ) {
+	wp_cache_delete( $user_id, 'bp_groups_memberships_for_user' );
+
+	$membership = new BP_Groups_Member( $user_id, $group_id );
+	wp_cache_delete( $membership->id, 'bp_groups_memberships' );
+}
+add_action( 'bp_groups_member_before_delete', 'bp_groups_clear_user_group_cache_on_other_events', 10, 2 );
+add_action( 'bp_groups_member_before_delete_invite', 'bp_groups_clear_user_group_cache_on_other_events', 10, 2 );
+
 /* List actions to clear super cached pages on, if super cache is installed */
 add_action( 'groups_join_group',                 'bp_core_clear_cache' );
 add_action( 'groups_leave_group',                'bp_core_clear_cache' );
diff --git src/bp-groups/bp-groups-functions.php src/bp-groups/bp-groups-functions.php
index 88c82bb..653a3ad 100644
--- src/bp-groups/bp-groups-functions.php
+++ src/bp-groups/bp-groups-functions.php
@@ -791,6 +791,116 @@ function groups_get_user_groups( $user_id = 0, $pag_num = 0, $pag_page = 0 ) {
 }
 
 /**
+ * Get a list of groups of which the specified user is a member.
+ *
+ * @since 2.6.0
+ *
+ * @param int $user_id ID of the user.
+ * @param array $args {
+ *     Array of optional args.
+ *     @param bool|null   $is_confirmed Whether to return only confirmed memberships. Pass `null` to disable this
+ *                                      filter. Default: true.
+ *     @param bool|null   $is_banned    Whether to return only banned memberships. Pass `null` to disable this filter.
+ *                                      Default: false.
+ *     @param bool|null   $is_admin     Whether to return only admin memberships. Pass `null` to disable this filter.
+ *                                      Default: false.
+ *     @param bool|null   $is_mod       Whether to return only mod memberships. Pass `null` to disable this filter.
+ *                                      Default: false.
+ *     @param bool|null   $invite_sent  Whether to return only memberships with 'invite_sent'. Pass `null` to disable
+ *                                      this filter. Default: false.
+ *     @param string      $orderby      Field to order by. Accepts 'id' (membership ID), 'group_id', 'date_modified'.
+ *                                      Default: 'group_id'.
+ *     @param string      $order        Sort order. Accepts 'ASC' or 'DESC'. Default: 'ASC'.
+ * }
+ * @return array Array of matching group memberships, keyed by group ID.
+ */
+function bp_get_user_groups( $user_id, $args = array() ) {
+	$r = bp_parse_args( $args, array(
+		'is_confirmed' => true,
+		'is_banned'    => false,
+		'is_admin'     => false,
+		'is_mod'       => false,
+		'invite_sent'  => null,
+		'orderby'      => 'group_id',
+		'order'        => 'ASC',
+	), 'get_user_groups' );
+
+	$user_id = intval( $user_id );
+
+	$membership_ids = wp_cache_get( $user_id, 'bp_groups_memberships_for_user' );
+	if ( false === $membership_ids ) {
+		$membership_ids = BP_Groups_Member::get_membership_ids_for_user( $user_id );
+		wp_cache_set( $user_id, $membership_ids, 'bp_groups_memberships_for_user' );
+	}
+
+	// Prime the membership cache.
+	$uncached_membership_ids = bp_get_non_cached_ids( $membership_ids, 'bp_groups_memberships' );
+	if ( ! empty( $uncached_membership_ids ) ) {
+		$uncached_memberships = BP_Groups_Member::get_memberships_by_id( $uncached_membership_ids );
+
+		foreach ( $uncached_memberships as $uncached_membership ) {
+			wp_cache_set( $uncached_membership->id, $uncached_membership, 'bp_groups_memberships' );
+		}
+	}
+
+	// Populate group membership array from cache.
+	$groups = array();
+	foreach ( $membership_ids as $membership_id ) {
+		$membership = wp_cache_get( $membership_id, 'bp_groups_memberships' );
+
+		// Sanity check.
+		if ( ! isset( $membership->group_id ) ) {
+			continue;
+		}
+
+		$group_id = (int) $membership->group_id;
+
+		$groups[ $group_id ] = $membership;
+	}
+
+	// Normalize group data.
+	foreach ( $groups as &$group ) {
+		// Integer values.
+		$group_id = intval( $group->group_id );
+		foreach ( array( 'id', 'group_id', 'user_id', 'inviter_id' ) as $index ) {
+			$group->{$index} = intval( $group->{$index} );
+		}
+
+		// Boolean values.
+		foreach ( array( 'is_admin', 'is_mod', 'is_confirmed', 'is_banned', 'invite_sent' ) as $index ) {
+			$group->{$index} = (bool) $group->{$index};
+		}
+	}
+
+	// Assemble filter array for use in `wp_list_filter()`.
+	$filters = wp_array_slice_assoc( $r, array( 'is_confirmed', 'is_banned', 'is_admin', 'is_mod', 'invite_sent' ) );
+	foreach ( $filters as $filter_name => $filter_value ) {
+		if ( is_null( $filter_value ) ) {
+			unset( $filters[ $filter_name ] );
+		}
+	}
+
+	if ( ! empty( $filters ) ) {
+		$groups = wp_list_filter( $groups, $filters );
+	}
+
+	// By default, results are ordered by membership id.
+	if ( 'group_id' === $r['orderby'] ) {
+		ksort( $groups );
+	} elseif ( in_array( $r['orderby'], array( 'id', 'date_modified' ) ) ) {
+		$groups = bp_sort_by_key( $groups, $r['orderby'] );
+	}
+
+	// By default, results are ordered ASC.
+	if ( 'DESC' === strtoupper( $r['order'] ) ) {
+		// `true` to preserve keys.
+		$groups = array_reverse( $groups, true );
+	}
+
+	return $groups;
+}
+
+/**
  * Get the count of groups of which the specified user is a member.
  *
  * @since 1.0.0
@@ -889,7 +999,17 @@ function groups_avatar_upload_dir( $group_id = 0 ) {
  * @return bool
  */
 function groups_is_user_admin( $user_id, $group_id ) {
-	return BP_Groups_Member::check_is_admin( $user_id, $group_id );
+	$is_admin = false;
+
+	$user_groups = bp_get_user_groups( $user_id, array(
+		'is_admin' => true,
+	) );
+
+	if ( isset( $user_groups[ $group_id ] ) ) {
+		$is_admin = $user_groups[ $group_id ]->id;
+	}
+
+	return $is_admin;
 }
 
 /**
@@ -902,7 +1022,17 @@ function groups_is_user_admin( $user_id, $group_id ) {
  * @return bool
  */
 function groups_is_user_mod( $user_id, $group_id ) {
-	return BP_Groups_Member::check_is_mod( $user_id, $group_id );
+	$is_mod = false;
+
+	$user_groups = bp_get_user_groups( $user_id, array(
+		'is_mod' => true,
+	) );
+
+	if ( isset( $user_groups[ $group_id ] ) ) {
+		$is_mod = $user_groups[ $group_id ]->id;
+	}
+
+	return $is_mod;
 }
 
 /**
@@ -915,7 +1045,18 @@ function groups_is_user_mod( $user_id, $group_id ) {
  * @return bool
  */
 function groups_is_user_member( $user_id, $group_id ) {
-	return BP_Groups_Member::check_is_member( $user_id, $group_id );
+	$is_member = false;
+
+	$user_groups = bp_get_user_groups( $user_id, array(
+		'is_admin' => null,
+		'is_mod' => null,
+	) );
+
+	if ( isset( $user_groups[ $group_id ] ) ) {
+		$is_member = $user_groups[ $group_id ]->id;
+	}
+
+	return $is_member;
 }
 
 /**
@@ -929,7 +1070,66 @@ function groups_is_user_member( $user_id, $group_id ) {
  * @return bool
  */
 function groups_is_user_banned( $user_id, $group_id ) {
-	return BP_Groups_Member::check_is_banned( $user_id, $group_id );
+	$is_banned = false;
+
+	$user_groups = bp_get_user_groups( $user_id, array(
+		'is_confirmed' => null,
+		'is_banned' => true,
+	) );
+
+	if ( isset( $user_groups[ $group_id ] ) ) {
+		$is_banned = $user_groups[ $group_id ]->id;
+	}
+
+	return $is_banned;
+}
+
+/**
+ * Check whether a user has an outstanding invitation to a group.
+ *
+ * @since 2.6.0
+ *
+ * @param int $user_id ID of the user.
+ * @param int $group_id ID of the group.
+ * @return int|null ID of the membership if found.
+ */
+function groups_is_user_invited( $user_id, $group_id ) {
+	$is_invited = false;
+
+	$user_groups = bp_get_user_groups( $user_id, array(
+		'invite_sent' => true,
+		'is_confirmed' => false,
+	) );
+
+	if ( isset( $user_groups[ $group_id ] ) ) {
+		$is_invited = $user_groups[ $group_id ]->id;
+	}
+
+	return $is_invited;
+}
+
+/**
+ * Check whether a user has a pending membership request for a group.
+ *
+ * @since 2.6.0
+ *
+ * @param int $user_id ID of the user.
+ * @param int $group_id ID of the group.
+ * @return int|null ID of the membership if found.
+ */
+function groups_is_user_pending( $user_id, $group_id ) {
+	$is_pending = false;
+
+	$user_groups = bp_get_user_groups( $user_id, array(
+		'invite_sent' => false,
+		'is_confirmed' => false,
+	) );
+
+	if ( isset( $user_groups[ $group_id ] ) ) {
+		$is_pending = $user_groups[ $group_id ]->id;
+	}
+
+	return $is_pending;
 }
 
 /**
diff --git src/bp-groups/classes/class-bp-groups-component.php src/bp-groups/classes/class-bp-groups-component.php
index 21aeb15..93bb9b7 100644
--- src/bp-groups/classes/class-bp-groups-component.php
+++ src/bp-groups/classes/class-bp-groups-component.php
@@ -845,7 +845,9 @@ class BP_Groups_Component extends BP_Component {
 			'bp_groups',
 			'bp_group_admins',
 			'bp_group_invite_count',
-			'group_meta'
+			'group_meta',
+			'bp_groups_memberships',
+			'bp_groups_memberships_for_user',
 		) );
 
 		parent::setup_cache_groups();
diff --git src/bp-groups/classes/class-bp-groups-group.php src/bp-groups/classes/class-bp-groups-group.php
index 659d2c4..d3e8d38 100644
--- src/bp-groups/classes/class-bp-groups-group.php
+++ src/bp-groups/classes/class-bp-groups-group.php
@@ -1422,69 +1422,14 @@ class BP_Groups_Group {
 	 * @return array $paged_groups
 	 */
 	public static function get_group_extras( &$paged_groups, &$group_ids, $type = false ) {
-		global $wpdb;
-
-		if ( empty( $group_ids ) )
-			return $paged_groups;
-
-		$bp = buddypress();
-
-		// Sanitize group IDs.
-		$group_ids = implode( ',', wp_parse_id_list( $group_ids ) );
-
-		// Fetch the logged-in user's status within each group.
-		if ( is_user_logged_in() ) {
-			$user_status_results = $wpdb->get_results( $wpdb->prepare( "SELECT group_id, is_confirmed, invite_sent FROM {$bp->groups->table_name_members} WHERE user_id = %d AND group_id IN ( {$group_ids} ) AND is_banned = 0", bp_loggedin_user_id() ) );
-		} else {
-			$user_status_results = array();
-		}
-
-		// Reindex.
-		$user_status = array();
-		foreach ( $user_status_results as $user_status_result ) {
-			$user_status[ $user_status_result->group_id ] = $user_status_result;
-		}
-
-		for ( $i = 0, $count = count( $paged_groups ); $i < $count; ++$i ) {
-			$is_member = $is_invited = $is_pending = '0';
-			$gid = $paged_groups[ $i ]->id;
-
-			if ( isset( $user_status[ $gid ] ) ) {
-
-				// The is_confirmed means the user is a member.
-				if ( $user_status[ $gid ]->is_confirmed ) {
-					$is_member = '1';
-
-				// The invite_sent means the user has been invited.
-				} elseif ( $user_status[ $gid ]->invite_sent ) {
-					$is_invited = '1';
-
-				// User has sent request, but has not been confirmed.
-				} else {
-					$is_pending = '1';
-				}
-			}
-
-			$paged_groups[ $i ]->is_member = $is_member;
-			$paged_groups[ $i ]->is_invited = $is_invited;
-			$paged_groups[ $i ]->is_pending = $is_pending;
-		}
-
-		if ( is_user_logged_in() ) {
-			$user_banned = $wpdb->get_col( $wpdb->prepare( "SELECT group_id FROM {$bp->groups->table_name_members} WHERE is_banned = 1 AND user_id = %d AND group_id IN ( {$group_ids} )", bp_loggedin_user_id() ) );
-		} else {
-			$user_banned = array();
-		}
-
-		for ( $i = 0, $count = count( $paged_groups ); $i < $count; ++$i ) {
-			$paged_groups[$i]->is_banned = false;
-
-			foreach ( (array) $user_banned as $group_id ) {
-				if ( $group_id == $paged_groups[$i]->id ) {
-					$paged_groups[$i]->is_banned = true;
-				}
-			}
-		}
+		$user_id = bp_loggedin_user_id();
+
+		foreach ( $paged_groups as &$group ) {
+			$group->is_member  = groups_is_user_member( $user_id, $group->id ) ? '1' : '0';
+			$group->is_invited = groups_is_user_invited( $user_id, $group->id ) ? '1' : '0';
+			$group->is_pending = groups_is_user_pending( $user_id, $group->id ) ? '1' : '0';
+			$group->is_banned  = (bool) groups_is_user_banned( $user_id, $group->id );
+  		}
 
 		return $paged_groups;
 	}
diff --git src/bp-groups/classes/class-bp-groups-member.php src/bp-groups/classes/class-bp-groups-member.php
index 68d315e..bfb1a76 100644
--- src/bp-groups/classes/class-bp-groups-member.php
+++ src/bp-groups/classes/class-bp-groups-member.php
@@ -821,6 +821,16 @@ class BP_Groups_Member {
 			return false;
 		}
 
+		/**
+		 * Fires before a group invitation is deleted.
+		 *
+		 * @since 2.6.0
+		 *
+		 * @param int $user_id  ID of the user.
+		 * @param int $group_id ID of the group.
+		 */
+		do_action( 'bp_groups_member_before_delete_invite', $user_id, $group_id );
+
 		$table_name = buddypress()->groups->table_name_members;
 
 		$sql = "DELETE FROM {$table_name}
@@ -1053,6 +1063,23 @@ class BP_Groups_Member {
 	}
 
 	/**
+	 * Get group membership objects by ID (or an array of IDs).
+	 *
+	 * @since 2.6.0
+	 *
+	 * @param int|string|array $membership_ids Single membership ID or comma-separated/array list of membership IDs.
+	 * @return array
+	 */
+	public static function get_memberships_by_id( $membership_ids ) {
+		global $wpdb;
+
+		$bp = buddypress();
+
+		$membership_ids = implode( ',', wp_parse_id_list( $membership_ids ) );
+		return $wpdb->get_results( "SELECT * FROM {$bp->groups->table_name_members} WHERE id IN ({$membership_ids})" );
+	}
+
+	/**
 	 * Get the IDs users with outstanding membership requests to the group.
 	 *
 	 * @since 1.6.0
@@ -1161,6 +1188,24 @@ class BP_Groups_Member {
 	}
 
 	/**
+	 * Get all membership IDs for a user.
+	 *
+	 * @since 2.6.0
+	 *
+	 * @param int $user_id ID of the user.
+	 * @return array
+	 */
+	public static function get_membership_ids_for_user( $user_id ) {
+		global $wpdb;
+
+		$bp = buddypress();
+
+		$group_ids = $wpdb->get_col( $wpdb->prepare( "SELECT id FROM {$bp->groups->table_name_members} WHERE user_id = %d ORDER BY id ASC", $user_id ) );
+
+		return $group_ids;
+	}
+
+	/**
 	 * Delete all memberships for a given group.
 	 *
 	 * @since 1.6.0
diff --git tests/phpunit/testcases/groups/class-bp-groups-member.php tests/phpunit/testcases/groups/class-bp-groups-member.php
index 7aea071..5447ced 100644
--- tests/phpunit/testcases/groups/class-bp-groups-member.php
+++ tests/phpunit/testcases/groups/class-bp-groups-member.php
@@ -1268,4 +1268,36 @@ class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase {
 	public function test_total_group_count_should_return_integer() {
 		$this->assertInternalType( 'int', BP_Groups_Member::total_group_count( 123 ) );
 	}
+
+	/**
+	 * @group get_memberships_by_id
+	 */
+	public function test_get_memberships_by_id_with_single_id() {
+		$users = $this->factory->user->create_many( 2 );
+		$groups = $this->factory->group->create_many( 2 );
+
+		$m0 = $this->add_user_to_group( $users[0], $groups[0] );
+		$m1 = $this->add_user_to_group( $users[1], $groups[1] );
+
+		$found = BP_Groups_Member::get_memberships_by_id( $m0 );
+
+		$this->assertSame( 1, count( $found ) );
+		$this->assertEquals( $m0, $found[0]->id );
+	}
+
+	/**
+	 * @group get_memberships_by_id
+	 */
+	public function test_get_memberships_by_id_with_multiple_ids() {
+		$users = $this->factory->user->create_many( 2 );
+		$groups = $this->factory->group->create_many( 2 );
+
+		$m0 = $this->add_user_to_group( $users[0], $groups[0] );
+		$m1 = $this->add_user_to_group( $users[1], $groups[1] );
+
+		$found = BP_Groups_Member::get_memberships_by_id( array( $m0, $m1 ) );
+
+		$this->assertSame( 2, count( $found ) );
+		$this->assertEqualSets( array( $m0, $m1 ), wp_list_pluck( $found, 'id' ) );
+	}
 }
diff --git tests/phpunit/testcases/groups/functions/groupsIsUser.php tests/phpunit/testcases/groups/functions/groupsIsUser.php
index 5a2abc3..b40df66 100644
--- tests/phpunit/testcases/groups/functions/groupsIsUser.php
+++ tests/phpunit/testcases/groups/functions/groupsIsUser.php
@@ -54,7 +54,7 @@ class BP_Tests_Groups_Functions_GroupsIsUser extends BP_UnitTestCase {
 			'is_admin' => true,
 		) );
 
-		$this->assertEquals( true, groups_is_user_admin( self::$user, self::$groups[1] ) );
+		$this->assertNotEmpty( groups_is_user_admin( self::$user, self::$groups[1] ) );
 	}
 
 	public function test_groups_is_user_admin_expected_false() {
@@ -76,7 +76,7 @@ class BP_Tests_Groups_Functions_GroupsIsUser extends BP_UnitTestCase {
 			'is_mod' => true,
 		) );
 
-		$this->assertEquals( true, groups_is_user_mod( self::$user, self::$groups[1] ) );
+		$this->assertNotEmpty( groups_is_user_mod( self::$user, self::$groups[1] ) );
 	}
 
 	public function test_groups_is_user_mod_expected_false() {
@@ -107,7 +107,23 @@ class BP_Tests_Groups_Functions_GroupsIsUser extends BP_UnitTestCase {
 	public function test_groups_is_user_member_expected_true() {
 		$this->add_user_to_group( self::$user, self::$groups[1] );
 
-		$this->assertEquals( true, groups_is_user_member( self::$user, self::$groups[1] ) );
+		$this->assertNotEmpty( groups_is_user_member( self::$user, self::$groups[1] ) );
+	}
+
+	public function test_groups_is_user_member_should_return_true_for_admin() {
+		$this->add_user_to_group( self::$user, self::$groups[1], array(
+			'is_admin' => true,
+		) );
+
+		$this->assertNotEmpty( groups_is_user_member( self::$user, self::$groups[1] ) );
+	}
+
+	public function test_groups_is_user_member_should_return_true_for_mod() {
+		$this->add_user_to_group( self::$user, self::$groups[1], array(
+			'is_mod' => true,
+		) );
+
+		$this->assertNotEmpty( groups_is_user_member( self::$user, self::$groups[1] ) );
 	}
 
 	public function test_groups_is_user_member_expected_false() {
@@ -143,6 +159,65 @@ class BP_Tests_Groups_Functions_GroupsIsUser extends BP_UnitTestCase {
 		$m = new BP_Groups_Member( self::$user, self::$groups[1] );
 		$m->ban();
 
-		$this->assertEquals( true, groups_is_user_banned( self::$user, self::$groups[1] ) );
+		$this->assertNotEmpty( groups_is_user_banned( self::$user, self::$groups[1] ) );
+	}
+
+	public function test_groups_is_user_invited_should_return_false_for_confirmed_member() {
+		$this->add_user_to_group( self::$user, self::$groups[1] );
+		$this->assertEquals( false, groups_is_user_invited( self::$user, self::$groups[1] ) );
+	}
+
+	public function test_groups_is_user_invited_should_return_false_for_uninvited_member() {
+		$this->assertEquals( false, groups_is_user_invited( self::$user, self::$groups[1] ) );
+	}
+
+	public function test_groups_is_user_invited_should_return_true_for_invited_member() {
+		$i = groups_invite_user( array(
+			'user_id' => self::$user,
+			'group_id' => self::$groups[1],
+			'inviter_id' => 123,
+		) );
+
+		// Send invite.
+		$m = new BP_Groups_Member( self::$user, self::$groups[1] );
+		$m->invite_sent = 1;
+		$m->save();
+
+		$this->assertNotEmpty( groups_is_user_invited( self::$user, self::$groups[1] ) );
+	}
+
+	public function test_groups_is_user_pending_should_return_false_for_pending_member() {
+		groups_invite_user( array(
+			'user_id' => self::$user,
+			'group_id' => self::$groups[1],
+			'inviter_id' => 123,
+		) );
+
+		// Send invite.
+		$m = new BP_Groups_Member( self::$user, self::$groups[1] );
+		$m->invite_sent = 1;
+		$m->save();
+
+		$this->assertEquals( false, groups_is_user_pending( self::$user, self::$groups[1] ) );
+	}
+
+	public function test_groups_is_user_pending_should_return_false_for_member_with_no_request() {
+		$this->assertEquals( false, groups_is_user_pending( self::$user, self::$groups[1] ) );
+	}
+
+	public function test_groups_is_user_pending_should_return_true_for_pending_member() {
+
+		$m                = new BP_Groups_Member;
+		$m->group_id      = self::$groups[1];
+		$m->user_id       = self::$user;
+		$m->inviter_id    = 0;
+		$m->is_admin      = 0;
+		$m->user_title    = '';
+		$m->date_modified = bp_core_current_time();
+		$m->is_confirmed  = 0;
+		$m->comments      = 'request';
+		$m->save();
+
+		$this->assertNotEmpty( groups_is_user_pending( self::$user, self::$groups[1] ) );
 	}
 }
