diff --git a/cms/djangoapps/contentstore/views/tests/test_item.py b/cms/djangoapps/contentstore/views/tests/test_item.py
index 74ed07989f5a0ce5385e98a04d935b09c11d3eb4..4d7216eb711502146a902d1fc213a9488deb9891 100644
--- a/cms/djangoapps/contentstore/views/tests/test_item.py
+++ b/cms/djangoapps/contentstore/views/tests/test_item.py
@@ -35,6 +35,7 @@ from cms.djangoapps.contentstore.tests.utils import CourseTestCase
 from cms.djangoapps.contentstore.utils import reverse_course_url, reverse_usage_url
 from cms.djangoapps.contentstore.views import item as item_module
 from lms_xblock.mixin import NONSENSICAL_ACCESS_RESTRICTION
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
 from student.tests.factories import UserFactory
 from xblock_django.models import XBlockConfiguration, XBlockStudioConfiguration, XBlockStudioConfigurationFlag
 from xblock_django.user_service import DjangoXBlockUserService
@@ -2666,7 +2667,7 @@ class TestXBlockInfo(ItemTest):
         self.course.highlights_enabled_for_messaging = True
         self.store.update_item(self.course, None)
         chapter = self.store.get_item(self.chapter.location)
-        with highlights_setting.override():
+        with override_waffle_switch(highlights_setting, active=True):
             chapter_xblock_info = create_xblock_info(chapter)
             course_xblock_info = create_xblock_info(self.course)
             self.assertTrue(chapter_xblock_info['highlights_enabled'])
diff --git a/cms/djangoapps/contentstore/views/tests/test_videos.py b/cms/djangoapps/contentstore/views/tests/test_videos.py
index 6cf01927b4128d04c8f7b487b6a0808bc68e2c7a..8e88f96eb6734e59be6e84c3d5e3c31b87c6252c 100644
--- a/cms/djangoapps/contentstore/views/tests/test_videos.py
+++ b/cms/djangoapps/contentstore/views/tests/test_videos.py
@@ -41,7 +41,9 @@ from openedx.core.djangoapps.video_pipeline.config.waffle import (
     waffle_flags
 )
 from openedx.core.djangoapps.video_pipeline.models import VEMPipelineIntegration
+from openedx.core.djangoapps.waffle_utils import WaffleSwitch
 from openedx.core.djangoapps.waffle_utils.models import WaffleFlagCourseOverrideModel
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
 from xmodule.modulestore.tests.factories import CourseFactory
 
 from ..videos import (
@@ -56,23 +58,7 @@ from ..videos import (
     convert_video_status
 )
 
-
-def override_switch(switch, active):
-    """
-    Overrides the given waffle switch to `active` boolean.
-
-    Arguments:
-        switch(str): switch name
-        active(bool): A boolean representing (to be overridden) value
-    """
-    def decorate(function):
-        @wraps(function)
-        def inner(*args, **kwargs):
-            with WAFFLE_SWITCHES.override(switch, active=active):
-                function(*args, **kwargs)
-        return inner
-
-    return decorate
+VIDEO_IMAGE_UPLOAD_ENABLED_SWITCH = WaffleSwitch(WAFFLE_SWITCHES, VIDEO_IMAGE_UPLOAD_ENABLED)
 
 
 class VideoUploadTestBase(object):
@@ -908,7 +894,7 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
         self.assertIn('error', response)
         self.assertEqual(response['error'], error_message)
 
-    @override_switch(VIDEO_IMAGE_UPLOAD_ENABLED, False)
+    @override_waffle_switch(VIDEO_IMAGE_UPLOAD_ENABLED_SWITCH, False)
     def test_video_image_upload_disabled(self):
         """
         Tests the video image upload when the feature is disabled.
@@ -917,7 +903,7 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
         response = self.client.post(video_image_upload_url, {'file': 'dummy_file'}, format='multipart')
         self.assertEqual(response.status_code, 404)
 
-    @override_switch(VIDEO_IMAGE_UPLOAD_ENABLED, True)
+    @override_waffle_switch(VIDEO_IMAGE_UPLOAD_ENABLED_SWITCH, True)
     def test_video_image(self):
         """
         Test video image is saved.
@@ -939,7 +925,7 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
 
         self.assertNotEqual(image_url1, image_url2)
 
-    @override_switch(VIDEO_IMAGE_UPLOAD_ENABLED, True)
+    @override_waffle_switch(VIDEO_IMAGE_UPLOAD_ENABLED_SWITCH, True)
     def test_video_image_no_file(self):
         """
         Test that an error error message is returned if upload request is incorrect.
@@ -948,7 +934,7 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
         response = self.client.post(video_image_upload_url, {})
         self.verify_error_message(response, 'An image file is required.')
 
-    @override_switch(VIDEO_IMAGE_UPLOAD_ENABLED, True)
+    @override_waffle_switch(VIDEO_IMAGE_UPLOAD_ENABLED_SWITCH, True)
     def test_no_video_image(self):
         """
         Test image url is set to None if no video image.
@@ -1130,7 +1116,7 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
         )
     )
     @ddt.unpack
-    @override_switch(VIDEO_IMAGE_UPLOAD_ENABLED, True)
+    @override_waffle_switch(VIDEO_IMAGE_UPLOAD_ENABLED_SWITCH, True)
     def test_video_image_validation_message(self, image_data, error_message):
         """
         Test video image validation gives proper error message.
diff --git a/common/djangoapps/student/tests/test_admin_views.py b/common/djangoapps/student/tests/test_admin_views.py
index d67b429ba1f16f236bcc0342859871839dbef37f..02f125179d6248b1ee7d4261cefb354bb1a700c9 100644
--- a/common/djangoapps/student/tests/test_admin_views.py
+++ b/common/djangoapps/student/tests/test_admin_views.py
@@ -18,13 +18,14 @@ from django.utils.timezone import now
 from mock import Mock
 from pytz import UTC
 
-from student.admin import AllowedAuthUserForm, COURSE_ENROLLMENT_ADMIN_SWITCH, UserAdmin, CourseEnrollmentForm
+from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
+from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
+from student.admin import COURSE_ENROLLMENT_ADMIN_SWITCH, AllowedAuthUserForm, CourseEnrollmentForm, UserAdmin
 from student.models import AllowedAuthUser, CourseEnrollment, LoginFailures
 from student.tests.factories import CourseEnrollmentFactory, UserFactory
 from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
 from xmodule.modulestore.tests.factories import CourseFactory
-from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
-from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
 
 
 class AdminCourseRolesPageTest(SharedModuleStoreTestCase):
@@ -243,7 +244,7 @@ class CourseEnrollmentAdminTest(SharedModuleStoreTestCase):
         """
         Ensure CourseEnrollmentAdmin views can be enabled with the waffle switch.
         """
-        with COURSE_ENROLLMENT_ADMIN_SWITCH.override(active=True):
+        with override_waffle_switch(COURSE_ENROLLMENT_ADMIN_SWITCH, active=True):
             response = getattr(self.client, method)(url)
         self.assertEqual(response.status_code, 200)
 
@@ -257,7 +258,7 @@ class CourseEnrollmentAdminTest(SharedModuleStoreTestCase):
             course_id=self.course.id,  # pylint: disable=no-member
         )
         search_url = '{}?q={}'.format(reverse('admin:student_courseenrollment_changelist'), self.user.username)
-        with COURSE_ENROLLMENT_ADMIN_SWITCH.override(active=True):
+        with override_waffle_switch(COURSE_ENROLLMENT_ADMIN_SWITCH, active=True):
             response = self.client.get(search_url)
         self.assertEqual(response.status_code, 200)
 
@@ -283,7 +284,7 @@ class CourseEnrollmentAdminTest(SharedModuleStoreTestCase):
             'mode': self.course_enrollment.mode,
         }
 
-        with COURSE_ENROLLMENT_ADMIN_SWITCH.override(active=True):
+        with override_waffle_switch(COURSE_ENROLLMENT_ADMIN_SWITCH, active=True):
             response = self.client.post(
                 reverse('admin:student_courseenrollment_change', args=(self.course_enrollment.id, )),
                 data=data,
@@ -304,7 +305,7 @@ class CourseEnrollmentAdminTest(SharedModuleStoreTestCase):
             'mode': self.course_enrollment.mode,
         }
 
-        with COURSE_ENROLLMENT_ADMIN_SWITCH.override(active=True):
+        with override_waffle_switch(COURSE_ENROLLMENT_ADMIN_SWITCH, active=True):
             with self.assertRaises(ValidationError):
                 self.client.post(
                     reverse('admin:student_courseenrollment_change', args=(self.course_enrollment.id, )),
diff --git a/lms/djangoapps/certificates/tests/test_signals.py b/lms/djangoapps/certificates/tests/test_signals.py
index 87fcc6eb824534292a73f094a2f27aefaf1e8c80..3efdf947bbeb77a00381bd292f0b6ee5fdb90552 100644
--- a/lms/djangoapps/certificates/tests/test_signals.py
+++ b/lms/djangoapps/certificates/tests/test_signals.py
@@ -20,10 +20,14 @@ from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory
 from lms.djangoapps.grades.tests.utils import mock_passing_grade
 from lms.djangoapps.verify_student.models import IDVerificationAttempt, SoftwareSecurePhotoVerification
 from openedx.core.djangoapps.certificates.config import waffle
+from openedx.core.djangoapps.waffle_utils import WaffleSwitch
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
 from student.tests.factories import CourseEnrollmentFactory, UserFactory
 from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
 from xmodule.modulestore.tests.factories import CourseFactory
 
+AUTO_CERTIFICATE_GENERATION_SWITCH = WaffleSwitch(waffle.waffle(), waffle.AUTO_CERTIFICATE_GENERATION)
+
 
 class SelfGeneratedCertsSignalTest(ModuleStoreTestCase):
     """
@@ -84,13 +88,13 @@ class WhitelistGeneratedCertificatesTest(ModuleStoreTestCase):
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None
         ) as mock_generate_certificate_apply_async:
-            with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=False):
+            with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=False):
                 CertificateWhitelist.objects.create(
                     user=self.user,
                     course_id=self.course.id
                 )
                 mock_generate_certificate_apply_async.assert_not_called()
-            with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
+            with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
                 CertificateWhitelist.objects.create(
                     user=self.user,
                     course_id=self.course.id
@@ -112,13 +116,13 @@ class WhitelistGeneratedCertificatesTest(ModuleStoreTestCase):
                 'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
                 return_value=None
         ) as mock_generate_certificate_apply_async:
-            with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=False):
+            with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=False):
                 CertificateWhitelist.objects.create(
                     user=self.user,
                     course_id=self.ip_course.id
                 )
                 mock_generate_certificate_apply_async.assert_not_called()
-            with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
+            with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
                 CertificateWhitelist.objects.create(
                     user=self.user,
                     course_id=self.ip_course.id
@@ -167,7 +171,7 @@ class PassingGradeCertsTest(ModuleStoreTestCase):
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None
         ) as mock_generate_certificate_apply_async:
-            with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
+            with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
                 grade_factory = CourseGradeFactory()
                 # Not passing
                 grade_factory.update(self.user, self.course)
@@ -188,7 +192,7 @@ class PassingGradeCertsTest(ModuleStoreTestCase):
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None
         ) as mock_generate_certificate_apply_async:
-            with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
+            with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
                 grade_factory = CourseGradeFactory()
                 # Not passing
                 grade_factory.update(self.user, self.ip_course)
@@ -312,7 +316,7 @@ class LearnerTrackChangeCertsTest(ModuleStoreTestCase):
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None
         ) as mock_generate_certificate_apply_async:
-            with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
+            with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
                 mock_generate_certificate_apply_async.assert_not_called()
                 attempt = SoftwareSecurePhotoVerification.objects.create(
                     user=self.user_one,
@@ -333,7 +337,7 @@ class LearnerTrackChangeCertsTest(ModuleStoreTestCase):
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None
         ) as mock_generate_certificate_apply_async:
-            with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
+            with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
                 mock_generate_certificate_apply_async.assert_not_called()
                 attempt = SoftwareSecurePhotoVerification.objects.create(
                     user=self.user_two,
@@ -386,7 +390,7 @@ class CertificateGenerationTaskTest(ModuleStoreTestCase):
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None
         ) as mock_generate_certificate_apply_async:
-            with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
+            with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
                 fire_ungenerated_certificate_task(self.user, self.course.id)
                 task_created = mock_generate_certificate_apply_async.called
                 self.assertEqual(task_created, should_create)
diff --git a/lms/djangoapps/certificates/tests/test_webview_views.py b/lms/djangoapps/certificates/tests/test_webview_views.py
index a3997f33c643bce30356aa897d1d523c2f18ec67..aa2327a76973cbc285d158dc613db7f5e50d0784 100644
--- a/lms/djangoapps/certificates/tests/test_webview_views.py
+++ b/lms/djangoapps/certificates/tests/test_webview_views.py
@@ -14,8 +14,10 @@ from django.test.client import Client, RequestFactory
 from django.test.utils import override_settings
 from django.urls import reverse
 from mock import patch
+from urllib.parse import urlencode
 
 from course_modes.models import CourseMode
+from edx_toggles.toggles.testutils import override_waffle_switch
 from lms.djangoapps.badges.events.course_complete import get_completion_badge
 from lms.djangoapps.badges.tests.factories import (
     BadgeAssertionFactory,
@@ -44,6 +46,7 @@ from openedx.core.djangoapps.site_configuration.tests.test_util import (
     with_site_configuration,
     with_site_configuration_context
 )
+from openedx.core.djangoapps.waffle_utils import WaffleSwitch
 from openedx.core.djangolib.js_utils import js_escaped_string
 from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
 from openedx.core.lib.tests.assertions.events import assert_event_matches
@@ -55,6 +58,7 @@ from util.date_utils import strftime_localized
 from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
 from xmodule.modulestore.tests.factories import CourseFactory
 
+AUTO_CERTIFICATE_GENERATION_SWITCH = WaffleSwitch(waffle.waffle(), waffle.AUTO_CERTIFICATE_GENERATION)
 FEATURES_WITH_CERTS_ENABLED = settings.FEATURES.copy()
 FEATURES_WITH_CERTS_ENABLED['CERTIFICATES_HTML_VIEW'] = True
 FEATURES_WITH_BADGES_ENABLED = FEATURES_WITH_CERTS_ENABLED.copy()
@@ -937,7 +941,7 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
             expected_date = today
         else:
             expected_date = self.course.certificate_available_date
-        with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
+        with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
             response = self.client.get(test_url)
         date = u'{month} {day}, {year}'.format(
             month=strftime_localized(expected_date, "%B"),
diff --git a/lms/djangoapps/course_api/blocks/tests/test_api.py b/lms/djangoapps/course_api/blocks/tests/test_api.py
index 4b0fe82a42b31268fc2615bcb8013c37b712ffcb..bf8d2618666a2932dfc93b05946ac49ec32bd10c 100644
--- a/lms/djangoapps/course_api/blocks/tests/test_api.py
+++ b/lms/djangoapps/course_api/blocks/tests/test_api.py
@@ -11,7 +11,8 @@ from django.test.client import RequestFactory
 from mock import patch
 
 from openedx.core.djangoapps.content.block_structure.api import clear_course_from_cache
-from openedx.core.djangoapps.content.block_structure.config import STORAGE_BACKING_FOR_CACHE, waffle
+from openedx.core.djangoapps.content.block_structure.config import STORAGE_BACKING_FOR_CACHE, waffle_switch
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
 from student.tests.factories import UserFactory
 from xmodule.modulestore import ModuleStoreEnum
 from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
@@ -229,7 +230,7 @@ class TestGetBlocksQueryCounts(TestGetBlocksQueryCountsBase):
     )
     @ddt.unpack
     def test_query_counts_cached(self, store_type, with_storage_backing):
-        with waffle().override(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
+        with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
             course = self._create_course(store_type)
             self._get_blocks(
                 course,
@@ -246,7 +247,7 @@ class TestGetBlocksQueryCounts(TestGetBlocksQueryCountsBase):
     @ddt.unpack
     def test_query_counts_uncached(self, store_type_tuple, with_storage_backing):
         store_type, expected_mongo_queries = store_type_tuple
-        with waffle().override(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
+        with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
             course = self._create_course(store_type)
             clear_course_from_cache(course.id)
 
diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py
index 005f864ea7605c065ad501f086246b7f946e0141..86b710932733e9f89d7d2cf8c043a022c9e1604a 100644
--- a/lms/djangoapps/courseware/tests/test_module_render.py
+++ b/lms/djangoapps/courseware/tests/test_module_render.py
@@ -48,21 +48,26 @@ from course_modes.models import CourseMode
 from lms.djangoapps.courseware import module_render as render
 from lms.djangoapps.courseware.access_response import AccessResponse
 from lms.djangoapps.courseware.courses import get_course_info_section, get_course_with_access
+from lms.djangoapps.courseware.field_overrides import OverrideFieldData
 from lms.djangoapps.courseware.masquerade import CourseMasquerade
 from lms.djangoapps.courseware.model_data import FieldDataCache
 from lms.djangoapps.courseware.models import StudentModule
 from lms.djangoapps.courseware.module_render import get_module_for_descriptor, hash_resource
 from lms.djangoapps.courseware.tests.factories import (
-    GlobalStaffFactory, RequestFactoryNoCsrf, StudentModuleFactory, UserFactory,
+    GlobalStaffFactory,
+    RequestFactoryNoCsrf,
+    StudentModuleFactory,
+    UserFactory
 )
 from lms.djangoapps.courseware.tests.test_submitting_problems import TestSubmittingProblems
 from lms.djangoapps.courseware.tests.tests import LoginEnrollmentTestCase
-from lms.djangoapps.courseware.field_overrides import OverrideFieldData
 from lms.djangoapps.lms_xblock.field_data import LmsFieldData
 from openedx.core.djangoapps.credit.api import set_credit_requirement_status, set_credit_requirements
 from openedx.core.djangoapps.credit.models import CreditCourse
 from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user
-from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory, AccessTokenFactory
+from openedx.core.djangoapps.oauth_dispatch.tests.factories import AccessTokenFactory, ApplicationFactory
+from openedx.core.djangoapps.waffle_utils import WaffleSwitch
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
 from openedx.core.lib.courses import course_image_url
 from openedx.core.lib.gating import api as gating_api
 from openedx.core.lib.url_utils import quote_slashes
@@ -86,6 +91,10 @@ from xmodule.x_module import STUDENT_VIEW, CombinedSystem, XModule, XModuleDescr
 
 TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT
 
+ENABLE_COMPLETION_TRACKING_SWITCH = WaffleSwitch(
+    completion_waffle.waffle(), completion_waffle.ENABLE_COMPLETION_TRACKING, __name__
+)
+
 
 @XBlock.needs("field-data")
 @XBlock.needs("i18n")
@@ -760,7 +769,7 @@ class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCas
     @ddt.unpack
     @XBlock.register_temp_plugin(StubCompletableXBlock, identifier='comp')
     def test_completion_events_with_completion_disabled(self, signal, data):
-        with completion_waffle.waffle().override(completion_waffle.ENABLE_COMPLETION_TRACKING, False):
+        with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, False):
             course = CourseFactory.create()
             block = ItemFactory.create(category='comp', parent=course)
             request = self.request_factory.post(
@@ -782,7 +791,7 @@ class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCas
 
     @XBlock.register_temp_plugin(StubCompletableXBlock, identifier='comp')
     def test_completion_signal_for_completable_xblock(self):
-        with completion_waffle.waffle().override(completion_waffle.ENABLE_COMPLETION_TRACKING, True):
+        with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True):
             course = CourseFactory.create()
             block = ItemFactory.create(category='comp', parent=course)
 
@@ -862,7 +871,7 @@ class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCas
 
     @XBlock.register_temp_plugin(StubCompletableXBlock, identifier='comp')
     def test_progress_signal_ignored_for_completable_xblock(self):
-        with completion_waffle.waffle().override(completion_waffle.ENABLE_COMPLETION_TRACKING, True):
+        with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True):
             course = CourseFactory.create()
             block = ItemFactory.create(category='comp', parent=course)
 
@@ -875,7 +884,7 @@ class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCas
 
     @XBlock.register_temp_plugin(XBlockWithoutCompletionAPI, identifier='no_comp')
     def test_progress_signal_processed_for_xblock_without_completion_api(self):
-        with completion_waffle.waffle().override(completion_waffle.ENABLE_COMPLETION_TRACKING, True):
+        with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True):
             course = CourseFactory.create()
             block = ItemFactory.create(category='no_comp', parent=course)
 
@@ -889,7 +898,7 @@ class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCas
 
     @XBlock.register_temp_plugin(StubCompletableXBlock, identifier='comp')
     def test_skip_handlers_for_masquerading_staff(self):
-        with completion_waffle.waffle().override(completion_waffle.ENABLE_COMPLETION_TRACKING, True):
+        with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True):
             course = CourseFactory.create()
             block = ItemFactory.create(category='comp', parent=course)
             request = self.request_factory.post(
diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py
index d058fcde8836e0e47e69519a2caa35bb1e0fc771..1007bc758ad9de736158f59f111e2c531cc4f9a0 100644
--- a/lms/djangoapps/courseware/tests/test_views.py
+++ b/lms/djangoapps/courseware/tests/test_views.py
@@ -65,7 +65,7 @@ from lms.djangoapps.courseware.user_state_client import DjangoXBlockUserStateCli
 from lms.djangoapps.courseware.views.index import show_courseware_mfe_link
 from lms.djangoapps.experiments.testutils import override_experiment_waffle_flag
 from lms.djangoapps.grades.config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT
-from lms.djangoapps.grades.config.waffle import waffle as grades_waffle
+from lms.djangoapps.grades.config.waffle import waffle_switch as grades_waffle_switch
 from lms.djangoapps.verify_student.models import VerificationDeadline
 from lms.djangoapps.verify_student.services import IDVerificationService
 from openedx.core.djangoapps.catalog.tests.factories import CourseFactory as CatalogCourseFactory
@@ -74,7 +74,7 @@ from openedx.core.djangoapps.content.course_overviews.models import CourseOvervi
 from openedx.core.djangoapps.crawlers.models import CrawlersConfig
 from openedx.core.djangoapps.credit.api import set_credit_requirements
 from openedx.core.djangoapps.credit.models import CreditCourse, CreditProvider
-from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES
+from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES, override_waffle_switch
 from openedx.core.djangolib.testing.utils import get_mock_request
 from openedx.core.lib.gating import api as gating_api
 from openedx.core.lib.url_utils import quote_slashes
@@ -1446,7 +1446,7 @@ class ProgressPageTests(ProgressPageBaseTests):
     def test_progress_queries(self, enable_waffle, initial, subsequent):
         ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1))
         self.setup_course()
-        with grades_waffle().override(ASSUME_ZERO_GRADE_IF_ABSENT, active=enable_waffle):
+        with override_waffle_switch(grades_waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT), active=enable_waffle):
             with self.assertNumQueries(
                 initial, table_blacklist=QUERY_COUNT_TABLE_BLACKLIST
             ), check_mongo_calls(1):
diff --git a/lms/djangoapps/email_marketing/tests/test_signals.py b/lms/djangoapps/email_marketing/tests/test_signals.py
index 43d158e9aae551b6689cbf752b64002389ea6365..d21c2d0e94da426fb803705722f550f88b910e86 100644
--- a/lms/djangoapps/email_marketing/tests/test_signals.py
+++ b/lms/djangoapps/email_marketing/tests/test_signals.py
@@ -7,6 +7,7 @@ import datetime
 import logging
 
 import ddt
+import six
 from django.conf import settings
 from django.contrib.auth.models import AnonymousUser
 from django.contrib.sites.models import Site
@@ -17,16 +18,8 @@ from mock import ANY, Mock, patch
 from opaque_keys.edx.keys import CourseKey
 from sailthru.sailthru_error import SailthruClientError
 from sailthru.sailthru_response import SailthruResponse
-import six
 from testfixtures import LogCapture
 
-from ..models import EmailMarketingConfiguration
-from ..signals import (
-    add_email_marketing_cookies,
-    email_marketing_register_user,
-    email_marketing_user_field_changed,
-    update_sailthru
-)
 from lms.djangoapps.email_marketing.tasks import (
     _create_user_list,
     _get_list_from_email_marketing_provider,
@@ -41,6 +34,14 @@ from student.models import Registration
 from student.tests.factories import CourseEnrollmentFactory, UserFactory, UserProfileFactory
 from util.json_request import JsonResponse
 
+from ..models import EmailMarketingConfiguration
+from ..signals import (
+    add_email_marketing_cookies,
+    email_marketing_register_user,
+    email_marketing_user_field_changed,
+    update_sailthru
+)
+
 log = logging.getLogger(__name__)
 
 LOGGER_NAME = "lms.djangoapps.email_marketing.signals"
@@ -620,7 +621,7 @@ class SailthruTests(TestCase):
     @patch('sailthru.sailthru_client.SailthruClient.purchase')
     @patch('sailthru.sailthru_client.SailthruClient.api_get')
     @patch('sailthru.sailthru_client.SailthruClient.api_post')
-    @patch('openedx.core.djangoapps.waffle_utils.WaffleSwitchNamespace.is_enabled')
+    @patch('edx_toggles.toggles.WaffleSwitchNamespace.is_enabled')
     def test_update_course_enrollment_whitelabel(
             self,
             switch,
@@ -645,7 +646,7 @@ class SailthruTests(TestCase):
         update_sailthru(None, self.user, 'verified', self.course_id)
         self.assertFalse(mock_sailthru_purchase.called)
 
-    @patch('openedx.core.djangoapps.waffle_utils.WaffleSwitchNamespace.is_enabled')
+    @patch('edx_toggles.toggles.WaffleSwitchNamespace.is_enabled')
     @patch('sailthru.sailthru_client.SailthruClient.purchase')
     def test_purchase_is_not_invoked(self, mock_sailthru_purchase, switch):
         """Make sure purchase is not called in the following condition:
@@ -655,7 +656,7 @@ class SailthruTests(TestCase):
         update_sailthru(None, self.user, 'verified', self.course_id)
         self.assertFalse(mock_sailthru_purchase.called)
 
-    @patch('openedx.core.djangoapps.waffle_utils.WaffleSwitchNamespace.is_enabled')
+    @patch('edx_toggles.toggles.WaffleSwitchNamespace.is_enabled')
     @patch('sailthru.sailthru_client.SailthruClient.purchase')
     def test_encoding_is_working_for_email_contains_unicode(self, mock_sailthru_purchase, switch):
         """Make sure encoding is working for emails contains unicode characters
diff --git a/lms/djangoapps/grades/config/waffle.py b/lms/djangoapps/grades/config/waffle.py
index fde298543212f005332d4cbb494acc80f6921fce..5280de8ee4cb9b3ed656b0060962057cae4891bc 100644
--- a/lms/djangoapps/grades/config/waffle.py
+++ b/lms/djangoapps/grades/config/waffle.py
@@ -4,7 +4,12 @@ waffle switches for the Grades app.
 """
 
 
-from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag, WaffleFlagNamespace, WaffleSwitchNamespace
+from openedx.core.djangoapps.waffle_utils import (
+    CourseWaffleFlag,
+    WaffleFlagNamespace,
+    WaffleSwitch,
+    WaffleSwitchNamespace
+)
 
 # Namespace
 WAFFLE_NAMESPACE = u'grades'
@@ -81,6 +86,16 @@ def waffle():
     return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Grades: ')
 
 
+def waffle_switch(name):
+    """
+    Return the corresponding namespaced waffle switch.
+
+    WARNING: do not replicate this pattern. Instead of declaring waffle switch names as strings, you should create
+    WaffleSwitch objects as top-level constants.
+    """
+    return WaffleSwitch(waffle(), name, module_name=__name__)
+
+
 def waffle_flags():
     """
     Returns the namespaced, cached, audited Waffle flags dictionary for Grades.
diff --git a/lms/djangoapps/grades/tests/test_course_grade.py b/lms/djangoapps/grades/tests/test_course_grade.py
index 6920621fdc7aa6a0669aba7182b901479273c2fc..bf8fd188affebd04c4f1aefa4bf23c0afa41273f 100644
--- a/lms/djangoapps/grades/tests/test_course_grade.py
+++ b/lms/djangoapps/grades/tests/test_course_grade.py
@@ -4,13 +4,14 @@ from crum import set_current_request
 from django.conf import settings
 from mock import patch
 
+from edx_toggles.toggles.testutils import override_waffle_switch
 from openedx.core.djangolib.testing.utils import get_mock_request
 from student.models import CourseEnrollment
 from student.tests.factories import UserFactory
 from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
 from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
 
-from ..config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT, waffle
+from ..config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT, waffle_switch
 from ..course_data import CourseData
 from ..course_grade import ZeroCourseGrade
 from ..course_grade_factory import CourseGradeFactory
@@ -31,7 +32,7 @@ class ZeroGradeTest(GradeTestBase):
         """
         Creates a ZeroCourseGrade and ensures it's empty.
         """
-        with waffle().override(ASSUME_ZERO_GRADE_IF_ABSENT, active=assume_zero_enabled):
+        with override_waffle_switch(waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT), active=assume_zero_enabled):
             course_data = CourseData(self.request.user, structure=self.course_structure)
             chapter_grades = ZeroCourseGrade(self.request.user, course_data).chapter_grades
             for chapter in chapter_grades:
@@ -46,7 +47,7 @@ class ZeroGradeTest(GradeTestBase):
         """
         Creates a zero course grade and ensures that null scores aren't included in the section problem scores.
         """
-        with waffle().override(ASSUME_ZERO_GRADE_IF_ABSENT, active=assume_zero_enabled):
+        with override_waffle_switch(waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT), active=assume_zero_enabled):
             with patch('lms.djangoapps.grades.subsection_grade.get_score', return_value=None):
                 course_data = CourseData(self.request.user, structure=self.course_structure)
                 chapter_grades = ZeroCourseGrade(self.request.user, course_data).chapter_grades
diff --git a/lms/djangoapps/grades/tests/test_course_grade_factory.py b/lms/djangoapps/grades/tests/test_course_grade_factory.py
index fe1b193870a20f64aed3091fa215717e8d065576..4ced0b961afae4a940e1e8b61028c1a2a49038d3 100644
--- a/lms/djangoapps/grades/tests/test_course_grade_factory.py
+++ b/lms/djangoapps/grades/tests/test_course_grade_factory.py
@@ -9,7 +9,7 @@ import ddt
 from django.conf import settings
 from mock import patch
 from six import text_type
-
+from edx_toggles.toggles.testutils import override_waffle_switch
 from lms.djangoapps.courseware.access import has_access
 from lms.djangoapps.grades.config.tests.utils import persistent_grades_feature_flags
 from openedx.core.djangoapps.content.block_structure.factory import BlockStructureFactory
@@ -17,7 +17,7 @@ from student.tests.factories import UserFactory
 from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
 from xmodule.modulestore.tests.factories import CourseFactory
 
-from ..config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT, waffle
+from ..config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT, waffle_switch
 from ..course_grade import CourseGrade, ZeroCourseGrade
 from ..course_grade_factory import CourseGradeFactory
 from ..subsection_grade import ReadSubsectionGrade, ZeroSubsectionGrade
@@ -132,7 +132,7 @@ class TestCourseGradeFactory(GradeTestBase):
     @ddt.data(*itertools.product((True, False), (True, False)))
     @ddt.unpack
     def test_read_zero(self, assume_zero_enabled, create_if_needed):
-        with waffle().override(ASSUME_ZERO_GRADE_IF_ABSENT, active=assume_zero_enabled):
+        with override_waffle_switch(waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT), active=assume_zero_enabled):
             grade_factory = CourseGradeFactory()
             course_grade = grade_factory.read(self.request.user, self.course, create_if_needed=create_if_needed)
             if create_if_needed or assume_zero_enabled:
diff --git a/openedx/core/djangoapps/certificates/tests/test_api.py b/openedx/core/djangoapps/certificates/tests/test_api.py
index 319e727621c304b034332f19a5ec38e4fb67fc37..7cf4f508ac28995964085c6fd891ead667522b2b 100644
--- a/openedx/core/djangoapps/certificates/tests/test_api.py
+++ b/openedx/core/djangoapps/certificates/tests/test_api.py
@@ -13,6 +13,8 @@ from course_modes.models import CourseMode
 from openedx.core.djangoapps.certificates import api
 from openedx.core.djangoapps.certificates.config import waffle as certs_waffle
 from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
+from openedx.core.djangoapps.waffle_utils import WaffleSwitch
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
 from student.tests.factories import CourseEnrollmentFactory, UserFactory
 
 
@@ -66,8 +68,8 @@ class MockGeneratedCertificate(object):
 @contextmanager
 def configure_waffle_namespace(feature_enabled):
     namespace = certs_waffle.waffle()
-
-    with namespace.override(certs_waffle.AUTO_CERTIFICATE_GENERATION, active=feature_enabled):
+    auto_certificate_generation_switch = WaffleSwitch(namespace, certs_waffle.AUTO_CERTIFICATE_GENERATION)
+    with override_waffle_switch(auto_certificate_generation_switch, active=feature_enabled):
         yield
 
 
diff --git a/openedx/core/djangoapps/content/block_structure/config/__init__.py b/openedx/core/djangoapps/content/block_structure/config/__init__.py
index 05b0b4e7660eb09089857644f485a3ae3f85f1a4..c0df1cbe6d8c916bb3390ea8f9a8903784a30a24 100644
--- a/openedx/core/djangoapps/content/block_structure/config/__init__.py
+++ b/openedx/core/djangoapps/content/block_structure/config/__init__.py
@@ -4,7 +4,7 @@ waffle switches for the Block Structure framework.
 """
 
 
-from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace
+from openedx.core.djangoapps.waffle_utils import WaffleSwitch, WaffleSwitchNamespace
 from openedx.core.lib.cache_utils import request_cached
 
 from .models import BlockStructureConfiguration
@@ -25,6 +25,16 @@ def waffle():
     return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'BlockStructure: ')
 
 
+def waffle_switch(name):
+    """
+    Return the waffle switch associated to this namespace.
+
+    WARNING: do not replicate this pattern. Instead of declaring waffle switch names as strings, you should create
+    WaffleSwitch objects as top-level constants.
+    """
+    return WaffleSwitch(waffle(), name, module_name=__name__)
+
+
 @request_cached()
 def num_versions_to_keep():
     """
diff --git a/openedx/core/djangoapps/content/block_structure/management/commands/generate_course_blocks.py b/openedx/core/djangoapps/content/block_structure/management/commands/generate_course_blocks.py
index 7d9c22cebccab2eb9d7ddf42daae7cd5d71e409e..1ee189a52880e831e170e6dc569dce55030aeeab 100644
--- a/openedx/core/djangoapps/content/block_structure/management/commands/generate_course_blocks.py
+++ b/openedx/core/djangoapps/content/block_structure/management/commands/generate_course_blocks.py
@@ -133,7 +133,7 @@ class Command(BaseCommand):
         Generates course blocks for the given course_keys per the given options.
         """
         if options.get('with_storage'):
-            waffle().override_for_request(STORAGE_BACKING_FOR_CACHE)
+            waffle().set_request_cache_with_short_name(STORAGE_BACKING_FOR_CACHE, True)
 
         for course_key in course_keys:
             try:
diff --git a/openedx/core/djangoapps/content/block_structure/tasks.py b/openedx/core/djangoapps/content/block_structure/tasks.py
index 7301c3f6b6f71b08ab6cc8559caa49dfaa42fe93..5989a68e57b9888d58975437e46dff70e17cb878 100644
--- a/openedx/core/djangoapps/content/block_structure/tasks.py
+++ b/openedx/core/djangoapps/content/block_structure/tasks.py
@@ -60,7 +60,7 @@ def _update_course_in_cache(self, **kwargs):
     Updates the course blocks (mongo -> BlockStructure) for the specified course.
     """
     if kwargs.get('with_storage'):
-        waffle().override_for_request(STORAGE_BACKING_FOR_CACHE)
+        waffle().set_request_cache_with_short_name(STORAGE_BACKING_FOR_CACHE, True)
     _call_and_retry_if_needed(self, api.update_course_in_cache, **kwargs)
 
 
@@ -89,7 +89,7 @@ def _get_course_in_cache(self, **kwargs):
     Gets the course blocks for the specified course, updating the cache if needed.
     """
     if kwargs.get('with_storage'):
-        waffle().override_for_request(STORAGE_BACKING_FOR_CACHE)
+        waffle().set_request_cache_with_short_name(STORAGE_BACKING_FOR_CACHE, True)
     _call_and_retry_if_needed(self, api.get_course_in_cache, **kwargs)
 
 
diff --git a/openedx/core/djangoapps/content/block_structure/tests/test_manager.py b/openedx/core/djangoapps/content/block_structure/tests/test_manager.py
index 6fb13a3f2b586c3495dd6f6fe329293eb0b1381c..04d0c9a57ef5f1b762800f7738e4e1f05b2b7d88 100644
--- a/openedx/core/djangoapps/content/block_structure/tests/test_manager.py
+++ b/openedx/core/djangoapps/content/block_structure/tests/test_manager.py
@@ -7,8 +7,10 @@ import ddt
 import six
 from django.test import TestCase
 
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
+
 from ..block_structure import BlockStructureBlockData
-from ..config import RAISE_ERROR_WHEN_NOT_FOUND, STORAGE_BACKING_FOR_CACHE, waffle
+from ..config import RAISE_ERROR_WHEN_NOT_FOUND, STORAGE_BACKING_FOR_CACHE, waffle_switch
 from ..exceptions import BlockStructureNotFound, UsageKeyNotInBlockStructure
 from ..manager import BlockStructureManager
 from ..transformers import BlockStructureTransformers
@@ -178,14 +180,14 @@ class TestBlockStructureManager(UsageKeyFactoryMixin, ChildrenMapTestMixin, Test
         assert TestTransformer1.collect_call_count == 1
 
     def test_get_collected_error_raised(self):
-        with waffle().override(RAISE_ERROR_WHEN_NOT_FOUND, active=True):
+        with override_waffle_switch(waffle_switch(RAISE_ERROR_WHEN_NOT_FOUND), active=True):
             with mock_registered_transformers(self.registered_transformers):
                 with self.assertRaises(BlockStructureNotFound):
                     self.bs_manager.get_collected()
 
     @ddt.data(True, False)
     def test_update_collected_if_needed(self, with_storage_backing):
-        with waffle().override(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
+        with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
             with mock_registered_transformers(self.registered_transformers):
                 assert TestTransformer1.collect_call_count == 0
 
diff --git a/openedx/core/djangoapps/content/block_structure/tests/test_signals.py b/openedx/core/djangoapps/content/block_structure/tests/test_signals.py
index d1679edb39af382bbb395123b9f3e9e272cea935..ebea9613e63db69244c127a82a89522990d22046 100644
--- a/openedx/core/djangoapps/content/block_structure/tests/test_signals.py
+++ b/openedx/core/djangoapps/content/block_structure/tests/test_signals.py
@@ -7,12 +7,13 @@ import ddt
 from mock import patch
 from opaque_keys.edx.locator import CourseLocator, LibraryLocator
 
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
 from xmodule.modulestore.exceptions import ItemNotFoundError
 from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
 from xmodule.modulestore.tests.factories import CourseFactory
 
 from ..api import get_block_structure_manager
-from ..config import INVALIDATE_CACHE_ON_PUBLISH, waffle
+from ..config import INVALIDATE_CACHE_ON_PUBLISH, waffle_switch
 from ..signals import update_block_structure_on_course_publish
 from .helpers import is_course_in_block_structure_cache
 
@@ -56,7 +57,7 @@ class CourseBlocksSignalTest(ModuleStoreTestCase):
     def test_cache_invalidation(self, invalidate_cache_enabled, mock_bs_manager_clear):
         test_display_name = "Jedi 101"
 
-        with waffle().override(INVALIDATE_CACHE_ON_PUBLISH, active=invalidate_cache_enabled):
+        with override_waffle_switch(waffle_switch(INVALIDATE_CACHE_ON_PUBLISH), active=invalidate_cache_enabled):
             self.course.display_name = test_display_name
             self.store.update_item(self.course, self.user.id)
 
diff --git a/openedx/core/djangoapps/content/block_structure/tests/test_store.py b/openedx/core/djangoapps/content/block_structure/tests/test_store.py
index aa35635ab4ad65640b132d90896baf09cb299dd0..5db54bd0fbd390ce697bb1e0dffe8bd1cbfbc718 100644
--- a/openedx/core/djangoapps/content/block_structure/tests/test_store.py
+++ b/openedx/core/djangoapps/content/block_structure/tests/test_store.py
@@ -5,9 +5,10 @@ Tests for block_structure/cache.py
 
 import ddt
 
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
 from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
 
-from ..config import STORAGE_BACKING_FOR_CACHE, waffle
+from ..config import STORAGE_BACKING_FOR_CACHE, waffle_switch
 from ..config.models import BlockStructureConfiguration
 from ..exceptions import BlockStructureNotFound
 from ..store import BlockStructureStore
@@ -47,13 +48,13 @@ class TestBlockStructureStore(UsageKeyFactoryMixin, ChildrenMapTestMixin, CacheI
 
     @ddt.data(True, False)
     def test_get_none(self, with_storage_backing):
-        with waffle().override(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
+        with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
             with self.assertRaises(BlockStructureNotFound):
                 self.store.get(self.block_structure.root_block_usage_key)
 
     @ddt.data(True, False)
     def test_add_and_get(self, with_storage_backing):
-        with waffle().override(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
+        with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
             self.store.add(self.block_structure)
             stored_value = self.store.get(self.block_structure.root_block_usage_key)
             self.assertIsNotNone(stored_value)
@@ -61,7 +62,7 @@ class TestBlockStructureStore(UsageKeyFactoryMixin, ChildrenMapTestMixin, CacheI
 
     @ddt.data(True, False)
     def test_delete(self, with_storage_backing):
-        with waffle().override(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
+        with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
             self.store.add(self.block_structure)
             self.store.delete(self.block_structure.root_block_usage_key)
             with self.assertRaises(BlockStructureNotFound):
@@ -74,7 +75,7 @@ class TestBlockStructureStore(UsageKeyFactoryMixin, ChildrenMapTestMixin, CacheI
             self.store.get(self.block_structure.root_block_usage_key)
 
     def test_uncached_with_storage(self):
-        with waffle().override(STORAGE_BACKING_FOR_CACHE, active=True):
+        with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=True):
             self.store.add(self.block_structure)
             self.mock_cache.map.clear()
             stored_value = self.store.get(self.block_structure.root_block_usage_key)
diff --git a/openedx/core/djangoapps/coursegraph/management/commands/tests/test_dump_to_neo4j.py b/openedx/core/djangoapps/coursegraph/management/commands/tests/test_dump_to_neo4j.py
index cf7ecd043a0340bfeae4a0a42b766007a855a898..4576332a13d3bbd758788172e06be102da73f880 100644
--- a/openedx/core/djangoapps/coursegraph/management/commands/tests/test_dump_to_neo4j.py
+++ b/openedx/core/djangoapps/coursegraph/management/commands/tests/test_dump_to_neo4j.py
@@ -10,29 +10,22 @@ import ddt
 import mock
 import six
 from django.core.management import call_command
-from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
-from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
-
-from openedx.core.djangolib.testing.utils import skip_unless_lms
 
-from openedx.core.djangoapps.coursegraph.management.commands.dump_to_neo4j import (
-    ModuleStoreSerializer
-)
-from openedx.core.djangoapps.coursegraph.management.commands.tests.utils import (
-    MockGraph,
-    MockNodeSelector,
-)
+import openedx.core.djangoapps.content.block_structure.config as block_structure_config
+from openedx.core.djangoapps.content.block_structure.signals import update_block_structure_on_course_publish
+from openedx.core.djangoapps.coursegraph.management.commands.dump_to_neo4j import ModuleStoreSerializer
+from openedx.core.djangoapps.coursegraph.management.commands.tests.utils import MockGraph, MockNodeSelector
 from openedx.core.djangoapps.coursegraph.tasks import (
-    serialize_item,
-    serialize_course,
     coerce_types,
+    serialize_course,
+    serialize_item,
     should_dump_course,
-    strip_branch_and_version,
-)
-from openedx.core.djangoapps.content.block_structure.signals import (
-    update_block_structure_on_course_publish
+    strip_branch_and_version
 )
-import openedx.core.djangoapps.content.block_structure.config as block_structure_config
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
+from openedx.core.djangolib.testing.utils import skip_unless_lms
+from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
+from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
 
 
 class TestDumpToNeo4jCommandBase(SharedModuleStoreTestCase):
@@ -507,7 +500,9 @@ class TestModuleStoreSerializer(TestDumpToNeo4jCommandBase):
         self.assertEqual(len(submitted), len(self.course_strings))
 
         # simulate one of the courses being published
-        with block_structure_config.waffle().override(block_structure_config.STORAGE_BACKING_FOR_CACHE):
+        with override_waffle_switch(
+            block_structure_config.waffle_switch(block_structure_config.STORAGE_BACKING_FOR_CACHE), True
+        ):
             update_block_structure_on_course_publish(None, self.course.id)
 
         # make sure only the published course was dumped
diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_login.py b/openedx/core/djangoapps/user_authn/views/tests/test_login.py
index cf2157e0b7d10a62c47514ca23aae3e9146621ee..c86e206e30c88a0b86288b5c947dc934c4990a69 100644
--- a/openedx/core/djangoapps/user_authn/views/tests/test_login.py
+++ b/openedx/core/djangoapps/user_authn/views/tests/test_login.py
@@ -32,6 +32,7 @@ from openedx.core.djangoapps.user_authn.views.login import (
     AllowedAuthUser,
     _check_user_auth_flow
 )
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
 from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
 from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
 from openedx.core.lib.api.test_utils import ApiTestCase
@@ -725,7 +726,7 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
             'THIRD_PARTY_AUTH_ONLY_HINT': provider_tpa_hint,
         }
 
-        with ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY.override(switch_enabled):
+        with override_waffle_switch(ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY, switch_enabled):
             if not is_third_party_authenticated:
                 site = self.set_up_site(allowed_domain, default_site_configuration_values)
 
@@ -778,7 +779,7 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
             'THIRD_PARTY_AUTH_ONLY_HINT': provider_tpa_hint,
         }
 
-        with ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY.override(True):
+        with override_waffle_switch(ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY, True):
             site = self.set_up_site(allowed_domain, default_site_configuration_values)
 
             with self.assertLogs(level='WARN') as log:
diff --git a/openedx/core/djangoapps/waffle_utils/__init__.py b/openedx/core/djangoapps/waffle_utils/__init__.py
index 98a3b4afd756d9adf747413bb71846c3cfea412a..72e6912856536c0c5a2086a4f00bf0469ef7b57b 100644
--- a/openedx/core/djangoapps/waffle_utils/__init__.py
+++ b/openedx/core/djangoapps/waffle_utils/__init__.py
@@ -3,97 +3,15 @@ Extra utilities for waffle: most classes are defined in edx_toggles.toggles (htt
 we keep here some extra classes for usage within edx-platform. These classes cover course override use cases.
 """
 import logging
-from contextlib import contextmanager
 
 from opaque_keys.edx.keys import CourseKey
 
-from edx_toggles.toggles import WaffleFlag, WaffleFlagNamespace
-from edx_toggles.toggles import WaffleSwitch as BaseWaffleSwitch
-from edx_toggles.toggles import WaffleSwitchNamespace as BaseWaffleSwitchNamespace
+# pylint: disable=unused-import
+from edx_toggles.toggles import WaffleFlag, WaffleFlagNamespace, WaffleSwitch, WaffleSwitchNamespace
 
 log = logging.getLogger(__name__)
 
 
-class WaffleSwitchNamespace(BaseWaffleSwitchNamespace):
-    """
-    Waffle switch namespace that implements custom overriding methods. We should eventually get rid of this class.
-
-    To test WaffleSwitchNamespace, use the provided context managers.  For example:
-
-        with WAFFLE_SWITCHES.override(waffle.ESTIMATE_FIRST_ATTEMPTED, active=True):
-            ...
-
-    Note: this should eventually be deprecated in favour of a dedicated `override_waffle_switch` context manager.
-    """
-
-    @contextmanager
-    def override(self, switch_name, active=True):
-        """
-        Overrides the active value for the given switch for the duration of this
-        contextmanager.
-        Note: The value is overridden in the request cache AND in the model.
-        """
-        previous_active = self.is_enabled(switch_name)
-        try:
-            self.override_for_request(switch_name, active)
-            with self.override_in_model(switch_name, active):
-                yield
-        finally:
-            self.override_for_request(switch_name, previous_active)
-
-    def override_for_request(self, switch_name, active=True):
-        """
-        Overrides the active value for the given switch for the remainder of
-        this request (as this is not a context manager).
-        Note: The value is overridden in the request cache, not in the model.
-        """
-        namespaced_switch_name = self._namespaced_name(switch_name)
-        self._cached_switches[namespaced_switch_name] = active
-        log.info(
-            "%sSwitch '%s' set to %s for request.",
-            self.log_prefix,
-            namespaced_switch_name,
-            active,
-        )
-
-    @contextmanager
-    def override_in_model(self, switch_name, active=True):
-        """
-        Overrides the active value for the given switch for the duration of this
-        contextmanager.
-        Note: The value is overridden in the model, not the request cache.
-        Note: This should probably be moved to a test class.
-        """
-        # Import is placed here to avoid model import at project startup.
-        # pylint: disable=import-outside-toplevel
-        from waffle.testutils import override_switch as waffle_override_switch
-
-        namespaced_switch_name = self._namespaced_name(switch_name)
-        with waffle_override_switch(namespaced_switch_name, active):
-            log.info(
-                "%sSwitch '%s' set to %s in model.",
-                self.log_prefix,
-                namespaced_switch_name,
-                active,
-            )
-            yield
-
-
-class WaffleSwitch(BaseWaffleSwitch):
-    """
-    This class should be removed in favour of edx_toggles.toggles.WaffleSwitch once we get rid of the
-    WaffleSwitchNamespace class.
-    """
-
-    NAMESPACE_CLASS = WaffleSwitchNamespace
-
-    @contextmanager
-    def override(self, active=True):
-        with self.waffle_namespace.override(self.switch_name, active):
-            yield
-
-
-
 class CourseWaffleFlag(WaffleFlag):
     """
     Represents a single waffle flag that can be forced on/off for a course. This class should be used instead of
diff --git a/openedx/core/djangoapps/waffle_utils/tests/test_init.py b/openedx/core/djangoapps/waffle_utils/tests/test_init.py
index e39359dc4f3979529ad922c45710471e64cf1076..92220ac7588fe7a8934f1d670d81128685309297 100644
--- a/openedx/core/djangoapps/waffle_utils/tests/test_init.py
+++ b/openedx/core/djangoapps/waffle_utils/tests/test_init.py
@@ -7,7 +7,8 @@ import ddt
 from django.test import TestCase
 from django.test.client import RequestFactory
 from django.test.utils import override_settings
-# Note that we really shouldn't import from edx_toggles' internal API
+# TODO: we really shouldn't import from edx_toggles' internal API, but that's currently the only way to mock the
+# monitoring functions.
 import edx_toggles.toggles.internal.waffle
 from edx_django_utils.cache import RequestCache
 from mock import call, patch
diff --git a/openedx/core/djangoapps/waffle_utils/testutils.py b/openedx/core/djangoapps/waffle_utils/testutils.py
index 03c44ce3a50799e5207bece6bc17c322aa3e24c0..896e81dffff157c1fc475915c1bc75080536c73d 100644
--- a/openedx/core/djangoapps/waffle_utils/testutils.py
+++ b/openedx/core/djangoapps/waffle_utils/testutils.py
@@ -5,7 +5,7 @@ Test utilities for waffle utilities.
 # Import from edx-toggles to preserve import paths
 # TODO: Deprecate and remove
 # pylint: disable=unused-import
-from edx_toggles.toggles.testutils import override_waffle_flag
+from edx_toggles.toggles.testutils import override_waffle_flag, override_waffle_switch
 
 # Can be used with FilteredQueryCountMixin.assertNumQueries() to blacklist
 # waffle tables. For example:
diff --git a/openedx/core/tests/test_admin_view.py b/openedx/core/tests/test_admin_view.py
index 7362a8c14610aa7b377ddae336d315242a2c8d5c..d7f3cae626b9979ee598af7b735c869cd50d6f93 100644
--- a/openedx/core/tests/test_admin_view.py
+++ b/openedx/core/tests/test_admin_view.py
@@ -4,10 +4,12 @@ Tests that verify that the admin view loads.
 This is not inside a django app because it is a global property of the system.
 """
 
-from django.test import TestCase, Client
+from django.test import Client, TestCase
 from django.urls import reverse
-from student.tests.factories import UserFactory, TEST_PASSWORD
+
 from openedx.core.djangoapps.user_authn.views.login import ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY
+from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
+from student.tests.factories import TEST_PASSWORD, UserFactory
 
 
 class TestAdminView(TestCase):
@@ -37,10 +39,10 @@ class TestAdminView(TestCase):
         assert response.status_code == 302
 
     def test_admin_login_redirect(self):
-        with ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY.override(True):
+        with override_waffle_switch(ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY, True):
             response = self.client.get(reverse('admin:login'))
             assert response.url == '/login?next=/admin'
             assert response.status_code == 302
-        with ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY.override(False):
+        with override_waffle_switch(ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY, False):
             response = self.client.get(reverse('admin:login'))
             assert response.template_name == ['admin/login.html']
diff --git a/openedx/tests/completion_integration/test_views.py b/openedx/tests/completion_integration/test_views.py
index 15be7248f38d09774187a47edf3cb761266ac96c..9f05624f0a28c3eff4c947c040bf89102dbdaa77 100644
--- a/openedx/tests/completion_integration/test_views.py
+++ b/openedx/tests/completion_integration/test_views.py
@@ -5,11 +5,11 @@ Test models, managers, and validators.
 
 
 import ddt
+import six
 from completion import waffle
 from completion.test_utils import CompletionWaffleTestMixin
 from django.urls import reverse
 from rest_framework.test import APIClient
-import six
 
 from openedx.core.djangolib.testing.utils import skip_unless_lms
 from student.tests.factories import CourseEnrollmentFactory, UserFactory