diff --git a/common/djangoapps/django_comment_common/models.py b/common/djangoapps/django_comment_common/models.py
index 7d9d56aef41ae157861d382e1cf887ee991280b3..a05facd66c06d64b7652ec949fdf58ecc54410cf 100644
--- a/common/djangoapps/django_comment_common/models.py
+++ b/common/djangoapps/django_comment_common/models.py
@@ -121,7 +121,14 @@ class Role(models.Model):
         """
         Returns True if the user has one of the given roles for the given course
         """
-        return Role.objects.filter(course_id=course_id, name__in=role_names, users=user).exists()
+        if 'roles' in getattr(user, '_prefetched_objects_cache', {}):
+            # Don't blow up the prefetch cache
+            return any(
+                role.course_id == course_id and role.name in role_names
+                for role in user.roles.all()
+            )
+        else:
+            return user.roles.filter(course_id=course_id, name__in=role_names).exists()
 
 
 class Permission(models.Model):
diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py
index 49f036f940895ce23b593ea4262e45c36de894aa..863a0d001604948596846193d1ea84483a21a95c 100644
--- a/common/djangoapps/student/models.py
+++ b/common/djangoapps/student/models.py
@@ -1195,13 +1195,19 @@ class CourseEnrollment(models.Model):
         if user.is_anonymous:
             return None
         try:
-            query = cls.objects
-            if select_related is not None:
-                query = query.select_related(*select_related)
-            return query.get(
-                user=user,
-                course_id=course_key
-            )
+            if 'courseenrollment' in getattr(user, '_prefetched_objects_cache', {}):
+                for enrollment in user.courseenrollment_set.all():
+                    if enrollment.course_id == course_key:
+                        return enrollment
+                return None
+            else:
+                query = cls.objects
+                if select_related is not None:
+                    query = query.select_related(*select_related)
+                return query.get(
+                    user=user,
+                    course_id=course_key
+                )
         except cls.DoesNotExist:
             return None
 
diff --git a/lms/djangoapps/course_api/tests/test_views.py b/lms/djangoapps/course_api/tests/test_views.py
index 012a5495a5b8523310af26d5b539f6203730c9a5..28f9c3569bd8fe81b25a0ea2fe952ca141d4d04e 100644
--- a/lms/djangoapps/course_api/tests/test_views.py
+++ b/lms/djangoapps/course_api/tests/test_views.py
@@ -277,6 +277,7 @@ class CourseDetailViewTestCase(CourseApiTestViewMixin, SharedModuleStoreTestCase
 })
 @override_settings(SEARCH_ENGINE="search.tests.mock_search_engine.MockSearchEngine")
 @override_settings(COURSEWARE_INDEX_NAME=TEST_INDEX_NAME)
+@ddt.ddt
 class CourseListSearchViewTest(CourseApiTestViewMixin, ModuleStoreTestCase, SearcherMixin):
     """
     Tests the search functionality of the courses API.
@@ -355,7 +356,8 @@ class CourseListSearchViewTest(CourseApiTestViewMixin, ModuleStoreTestCase, Sear
         self.assertEqual(res.data['pagination']['count'], 3)
         self.assertEqual(len(res.data['results']), 1)  # Should return a single course
 
-    def test_too_many_courses(self):
+    @ddt.data(True, False)
+    def test_too_many_courses(self, with_username):
         """
         Test that search results are limited to 100 courses, and that they don't
         blow up the database.
@@ -394,8 +396,14 @@ class CourseListSearchViewTest(CourseApiTestViewMixin, ModuleStoreTestCase, Sear
 
         for page in range(1, 12):
             RequestCache.clear_all_namespaces()
-            with self.assertNumQueries(query_counts[page - 1]):
-                response = self.verify_response(params={'page': page, 'page_size': 30})
+            expected_query_count = query_counts[page - 1]
+            if with_username:
+                expected_query_count += 4
+            with self.assertNumQueries(expected_query_count):
+                params = {'page': page, 'page_size': 30}
+                if with_username:
+                    params['username'] = self.audit_user.username
+                response = self.verify_response(params=params)
 
                 self.assertIn('results', response.data)
                 self.assertEqual(response.data['pagination']['count'], 303)
diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py
index cc6ee05f2e240010bce930984fc5d45982354d8d..e3da3d3a66f614c5a1a35e8e479f7ad041a5b1e0 100644
--- a/lms/djangoapps/courseware/courses.py
+++ b/lms/djangoapps/courseware/courses.py
@@ -25,7 +25,7 @@ from courseware.model_data import FieldDataCache
 from courseware.module_render import get_module
 from course_modes.models import CourseMode
 from django.conf import settings
-from django.db.models import Prefetch
+from django.db.models import Prefetch, prefetch_related_objects
 from django.urls import reverse
 from django.http import Http404, QueryDict
 from enrollment.api import get_course_enrollment_details
@@ -474,7 +474,8 @@ def get_courses(user, org=None, filter_=None):
         'COURSE_CATALOG_VISIBILITY_PERMISSION',
         settings.COURSE_CATALOG_VISIBILITY_PERMISSION
     )
-
+    if user.is_authenticated:
+        prefetch_related_objects([user], 'roles', 'courseenrollment_set', 'experimentdata_set')
     return LazySequence(
         (c for c in courses if has_access(user, permission_name, c)),
         est_len=courses.count()
diff --git a/openedx/core/djangoapps/config_model_utils/utils.py b/openedx/core/djangoapps/config_model_utils/utils.py
index eae11e1814939f57407d246bd7101cdaec2c0ab3..b97974ad96bfd03bff0bfc017922f83a0256ee9a 100644
--- a/openedx/core/djangoapps/config_model_utils/utils.py
+++ b/openedx/core/djangoapps/config_model_utils/utils.py
@@ -12,14 +12,24 @@ def is_in_holdback(user):
     """
     in_holdback = False
     if user and user.is_authenticated:
-        try:
-            holdback_value = ExperimentData.objects.get(
-                user=user,
-                experiment_id=EXPERIMENT_ID,
-                key=EXPERIMENT_DATA_HOLDBACK_KEY,
-            ).value
-            in_holdback = holdback_value == 'True'
-        except ExperimentData.DoesNotExist:
-            pass
+        if 'experimentdata' in getattr(user, '_prefetched_objects_cache', {}):
+            for experiment_data in user.experimentdata_set.all():
+                if (
+                    experiment_data.experiment_id == EXPERIMENT_ID and
+                    experiment_data.key == EXPERIMENT_DATA_HOLDBACK_KEY
+                ):
+                    in_holdback = experiment_data.value == 'True'
+                    break
+        else:
+            try:
+                holdback_value = ExperimentData.objects.get(
+                    user=user,
+                    experiment_id=EXPERIMENT_ID,
+                    key=EXPERIMENT_DATA_HOLDBACK_KEY,
+                ).value
+            except ExperimentData.DoesNotExist:
+                pass
+            else:
+                in_holdback = holdback_value == 'True'
 
     return in_holdback