diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/adapters/keycloak.py b/SAS/TMSS/backend/src/tmss/tmssapp/adapters/keycloak.py
index d36413a4d56bf098ae2dc754da2773a8bfa856cf..7ddf72eb7a128fb49a32265074126604be029db7 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/adapters/keycloak.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/adapters/keycloak.py
@@ -44,7 +44,12 @@ def get_users_by_role_in_project(role, project):
     """
     returns the list of users that have the specified role in the specified project
     """
-    project_persons = get_project_persons()
+    # we fetch all and cache them instead of hitting Keycloak every time this gets called.
+    # But we don't care about all the legacy projects, so only request what's known to TMSS.
+    # This also works but is a little less efficient (for a relatively small number of projects):
+    # project_persons = get_project_persons(include_projects=(project,))
+    projects_known_to_tmss = models.Project.objects.values_list('name', flat=True)
+    project_persons = get_project_persons(include_projects=tuple(projects_known_to_tmss))
     if project in project_persons:
         return project_persons[project][role]
     else:
@@ -52,10 +57,11 @@ def get_users_by_role_in_project(role, project):
 
 
 @cachetools.func.ttl_cache(ttl=600)
-def get_project_persons():
+def get_project_persons(include_projects: tuple = None):
     """
     returns a mapping of projects names to a dict that contains the users that
     have a particular role in that project.
+    Optionally filter for a list of projects to include in the response.
     """
     project_persons_map = {}
     with KeycloakAdminAPISession() as ksession:
@@ -64,47 +70,48 @@ def get_project_persons():
             if group['name'] == 'Project':
                 projects = group['subGroups']
         for project in projects:
-            project_detail = ksession.get(url='%s/groups/%s/' % (KEYCLOAK_API_BASE_URL, project['id']))
-            attributes = project_detail.get('attributes', {})
-
-            legacy_role_keys = {'pi': 'lofarProjectPI',
-                                'friend_of_project': 'lofarProjectFriend',
-                                'contact': 'lofarProjectContactauthor'}
-
-            for project_role in models.ProjectRole.Choices:
-                # get role attribute from project:
-                role = project_role.value
-                users = attributes.get(role, [])
-                # fall back to legacy-style attribute:
-                if not users and role in legacy_role_keys:
-                    users = attributes.get(legacy_role_keys[role], [])
-
-                # convert user list (LDAP DNs) to something we can use in TMSS (email)
-                user_map = get_user_mapping()
-                mapped_users = [user_map[user] for user in users if user in user_map]  # email list of referenced users
-                unmappable_users = [user for user in users if user not in user_map]  # list of references for which no account was found
-                for unmappable_user in unmappable_users:
-                    # Note: Usually Keycloak should return DN references to user accounts. For PI's, someone had the
-                    # great idea to allow to specify a freeform string instead, to refer to people who may or may not
-                    # have an account. Even if the person has a user account, there is no way to replicate the exact
-                    # string 'representation' Keycloak returns, since the string may contain typos, or info that is not
-                    # stored in the user accounts (like titles).
-                    # The following unsafe hack tries to determine whether there is a user account that matches the
-                    # name given in the string (ignore titles since they are not part of the user account):
-                    # unmappable_user_fixed = re.sub('Dr\.', '', unmappable_user)
-                    # unmappable_user_fixed = re.sub('Prof\.', '', unmappable_user_fixed)
-                    # unmappable_user_fixed = re.sub('ir\.', '', unmappable_user_fixed)
-                    # unmappable_user_fixed = re.sub('Ir\.', '', unmappable_user_fixed)
-                    # unmappable_user_fixed = re.sub('apl\.', '', unmappable_user_fixed)
-                    # unmappable_user_fixed = re.sub(' +', ' ', unmappable_user_fixed)
-                    #
-                    # if unmappable_user_fixed in user_map:
-                    #     mapped_users.append(user_map[unmappable_user_fixed])
-                    # else:
-                        logger.warning("Could not match Keycloak user reference '%s' to a known user." % unmappable_user)
-                        if not unmappable_user.startswith('cn='):
-                            logger.warning("LOFAR allowed to reference a person by a freeform string instead of a user account. '%s' seems to be such a legacy reference. This needs to be fixed in the identity management." % unmappable_user)
-                project_persons_map.setdefault(project['name'], {})[role] = mapped_users
+            if include_projects is None or project['name'] in include_projects:
+                project_detail = ksession.get(url='%s/groups/%s/' % (KEYCLOAK_API_BASE_URL, project['id']))
+                attributes = project_detail.get('attributes', {})
+
+                legacy_role_keys = {'pi': 'lofarProjectPI',
+                                    'friend_of_project': 'lofarProjectFriend',
+                                    'contact': 'lofarProjectContactauthor'}
+
+                for project_role in models.ProjectRole.Choices:
+                    # get role attribute from project:
+                    role = project_role.value
+                    users = attributes.get(role, [])
+                    # fall back to legacy-style attribute:
+                    if not users and role in legacy_role_keys:
+                        users = attributes.get(legacy_role_keys[role], [])
+
+                    # convert user list (LDAP DNs) to something we can use in TMSS (email)
+                    user_map = get_user_mapping()
+                    mapped_users = [user_map[user] for user in users if user in user_map]  # email list of referenced users
+                    unmappable_users = [user for user in users if user not in user_map]  # list of references for which no account was found
+                    for unmappable_user in unmappable_users:
+                        # Note: Usually Keycloak should return DN references to user accounts. For PI's, someone had the
+                        # great idea to allow to specify a freeform string instead, to refer to people who may or may not
+                        # have an account. Even if the person has a user account, there is no way to replicate the exact
+                        # string 'representation' Keycloak returns, since the string may contain typos, or info that is not
+                        # stored in the user accounts (like titles).
+                        # The following unsafe hack tries to determine whether there is a user account that matches the
+                        # name given in the string (ignore titles since they are not part of the user account):
+                        # unmappable_user_fixed = re.sub('Dr\.', '', unmappable_user)
+                        # unmappable_user_fixed = re.sub('Prof\.', '', unmappable_user_fixed)
+                        # unmappable_user_fixed = re.sub('ir\.', '', unmappable_user_fixed)
+                        # unmappable_user_fixed = re.sub('Ir\.', '', unmappable_user_fixed)
+                        # unmappable_user_fixed = re.sub('apl\.', '', unmappable_user_fixed)
+                        # unmappable_user_fixed = re.sub(' +', ' ', unmappable_user_fixed)
+                        #
+                        # if unmappable_user_fixed in user_map:
+                        #     mapped_users.append(user_map[unmappable_user_fixed])
+                        # else:
+                            logger.warning("Could not match Keycloak user reference '%s' to a known user." % unmappable_user)
+                            if not unmappable_user.startswith('cn='):
+                                logger.warning("LOFAR allowed to reference a person by a freeform string instead of a user account. '%s' seems to be such a legacy reference. This needs to be fixed in the identity management." % unmappable_user)
+                    project_persons_map.setdefault(project['name'], {})[role] = mapped_users
 
     return project_persons_map