diff --git a/cms/envs/common.py b/cms/envs/common.py
index b66b601dfac5fe06bb0cb314062be4f8891d0b65..35e252503f6336a664e4301dcfd816ee0ffe4cdb 100644
--- a/cms/envs/common.py
+++ b/cms/envs/common.py
@@ -472,12 +472,12 @@ XQUEUE_INTERFACE = {
 MIDDLEWARE_CLASSES = [
     'crum.CurrentRequestUserMiddleware',
 
-    # Clears request cache. This is a safer request cache.
-    'edx_django_utils.cache.middleware.RequestCacheMiddleware',
-
+    # Deprecated, but well entrenched RequestCache
     'openedx.core.djangoapps.request_cache.middleware.RequestCache',
 
-    'openedx.core.djangoapps.monitoring_utils.middleware.MonitoringMemoryMiddleware',
+    # A newer and safer request cache.
+    'edx_django_utils.cache.middleware.RequestCacheMiddleware',
+    'edx_django_utils.monitoring.middleware.MonitoringMemoryMiddleware',
 
     'openedx.core.djangoapps.header_control.middleware.HeaderControlMiddleware',
     'django.middleware.cache.UpdateCacheMiddleware',
diff --git a/common/djangoapps/student/views/dashboard.py b/common/djangoapps/student/views/dashboard.py
index efd54a1555a6c0380257aa359000fbce5785e2ba..441417804023f74a16eb5e2ab3d8751a6f9aa8a2 100644
--- a/common/djangoapps/student/views/dashboard.py
+++ b/common/djangoapps/student/views/dashboard.py
@@ -15,7 +15,7 @@ from django.urls import reverse
 from django.shortcuts import redirect
 from django.utils.translation import ugettext as _
 from django.views.decorators.csrf import ensure_csrf_cookie
-
+from edx_django_utils import monitoring as monitoring_utils
 from opaque_keys.edx.keys import CourseKey
 from pytz import UTC
 from six import text_type, iteritems
@@ -28,7 +28,6 @@ from edxmako.shortcuts import render_to_response, render_to_string
 from entitlements.models import CourseEntitlement
 from lms.djangoapps.commerce.utils import EcommerceService  # pylint: disable=import-error
 from lms.djangoapps.verify_student.services import IDVerificationService
-from openedx.core.djangoapps import monitoring_utils
 from openedx.core.djangoapps.catalog.utils import (
     get_programs,
     get_pseudo_session_for_entitlement,
diff --git a/common/djangoapps/student/views/management.py b/common/djangoapps/student/views/management.py
index 61fcbedc4876c73afe8386e8a41e55800ef93e02..891c9f6d35f0906f4114e1d0f7fa4f9b7d06c360 100644
--- a/common/djangoapps/student/views/management.py
+++ b/common/djangoapps/student/views/management.py
@@ -35,6 +35,7 @@ from django.utils.translation import get_language, ungettext
 from django.utils.translation import ugettext as _
 from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie
 from django.views.decorators.http import require_GET, require_POST
+from edx_django_utils import monitoring as monitoring_utils
 from eventtracking import tracker
 from ipware.ip import get_ip
 # Note that this lives in LMS, so this dependency should be refactored.
@@ -54,7 +55,6 @@ import track.views
 from course_modes.models import CourseMode
 from edxmako.shortcuts import render_to_response, render_to_string
 from entitlements.models import CourseEntitlement
-from openedx.core.djangoapps import monitoring_utils
 from openedx.core.djangoapps.catalog.utils import (
     get_programs_with_type,
 )
diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py
index 4c33a549c7d68f76c473e53d858c19a54e38d236..b87f1ec1e6f0715c7bacf7a1ee150378f4345f53 100644
--- a/lms/djangoapps/courseware/module_render.py
+++ b/lms/djangoapps/courseware/module_render.py
@@ -19,6 +19,7 @@ from django.urls import reverse
 from django.http import Http404, HttpResponse, HttpResponseForbidden
 from django.views.decorators.clickjacking import xframe_options_exempt
 from django.views.decorators.csrf import csrf_exempt
+from edx_django_utils.monitoring import set_custom_metrics_for_course_key, set_monitoring_transaction_name
 from edx_proctoring.services import ProctoringService
 from opaque_keys import InvalidKeyError
 from opaque_keys.edx.keys import CourseKey, UsageKey
@@ -51,7 +52,6 @@ from lms.djangoapps.verify_student.services import XBlockVerificationService
 from openedx.core.djangoapps.bookmarks.services import BookmarksService
 from openedx.core.djangoapps.crawlers.models import CrawlersConfig
 from openedx.core.djangoapps.credit.services import CreditService
-from openedx.core.djangoapps.monitoring_utils import set_custom_metrics_for_course_key, set_monitoring_transaction_name
 from openedx.core.djangoapps.util.user_utils import SystemUser
 from openedx.core.lib.gating.services import GatingService
 from openedx.core.lib.license import wrap_with_license
diff --git a/lms/djangoapps/courseware/user_state_client.py b/lms/djangoapps/courseware/user_state_client.py
index ff44da860f489de5fb1c5b3b8988ab663f62931a..7abbed791eec07ef52d3eb9681bb634dd454ab89 100644
--- a/lms/djangoapps/courseware/user_state_client.py
+++ b/lms/djangoapps/courseware/user_state_client.py
@@ -13,12 +13,12 @@ from django.core.paginator import Paginator
 from django.contrib.auth.models import User
 from django.db import transaction
 from django.db.utils import IntegrityError
+from edx_django_utils import monitoring as monitoring_utils
 from edx_user_state_client.interface import XBlockUserState, XBlockUserStateClient
 from xblock.fields import Scope
 
 import dogstats_wrapper as dog_stats_api
 from courseware.models import BaseStudentModuleHistory, StudentModule
-from openedx.core.djangoapps import monitoring_utils
 
 try:
     import simplejson as json
diff --git a/lms/djangoapps/courseware/views/index.py b/lms/djangoapps/courseware/views/index.py
index 50f0d82a69088b5ce23fb214245d430d5b521dbc..55f263d81f0f0066055c31ff0b2cb4eefda88d4b 100644
--- a/lms/djangoapps/courseware/views/index.py
+++ b/lms/djangoapps/courseware/views/index.py
@@ -19,6 +19,7 @@ from django.utils.translation import ugettext as _
 from django.views.decorators.cache import cache_control
 from django.views.decorators.csrf import ensure_csrf_cookie
 from django.views.generic import View
+from edx_django_utils.monitoring import set_custom_metrics_for_course_key
 from opaque_keys.edx.keys import CourseKey
 from web_fragments.fragment import Fragment
 
@@ -29,7 +30,6 @@ from lms.djangoapps.gating.api import get_entrance_exam_score_ratio, get_entranc
 from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory
 from openedx.core.djangoapps.crawlers.models import CrawlersConfig
 from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
-from openedx.core.djangoapps.monitoring_utils import set_custom_metrics_for_course_key
 from openedx.core.djangoapps.user_api.preferences.api import get_user_preference
 from openedx.core.djangoapps.util.user_messages import PageLevelMessages
 from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace, WaffleFlagNamespace, CourseWaffleFlag
diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py
index 61be589e4c49a9c8b4cf8facd5c963e1c92328fe..8ec7a810a9495962d0b80105a71fcd35544e0db7 100644
--- a/lms/djangoapps/courseware/views/views.py
+++ b/lms/djangoapps/courseware/views/views.py
@@ -27,6 +27,7 @@ from django.views.decorators.clickjacking import xframe_options_exempt
 from django.views.decorators.csrf import ensure_csrf_cookie
 from django.views.decorators.http import require_GET, require_http_methods, require_POST
 from django.views.generic import View
+from edx_django_utils.monitoring import set_custom_metrics_for_course_key
 from eventtracking import tracker
 from ipware.ip import get_ip
 from markupsafe import escape
@@ -81,7 +82,6 @@ from openedx.core.djangoapps.credit.api import (
     is_user_eligible_for_credit
 )
 from openedx.core.djangoapps.models.course_details import CourseDetails
-from openedx.core.djangoapps.monitoring_utils import set_custom_metrics_for_course_key
 from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
 from openedx.core.djangoapps.programs.utils import ProgramMarketingDataExtender
 from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration
diff --git a/lms/djangoapps/discussion/views.py b/lms/djangoapps/discussion/views.py
index b0dbdb4b9da914387730287a400655bf8e1249b2..8d08a1090fa460a7570f740ab1f76f93f22fbd83 100644
--- a/lms/djangoapps/discussion/views.py
+++ b/lms/djangoapps/discussion/views.py
@@ -17,6 +17,7 @@ from django.template.loader import render_to_string
 from django.utils.translation import get_language_bidi
 from django.views.decorators.csrf import ensure_csrf_cookie
 from django.views.decorators.http import require_GET, require_http_methods
+from edx_django_utils.monitoring import function_trace
 from opaque_keys.edx.keys import CourseKey
 from rest_framework import status
 from web_fragments.fragment import Fragment
@@ -44,7 +45,6 @@ from django_comment_client.utils import (
 from django_comment_common.models import CourseDiscussionSettings
 from django_comment_common.utils import ThreadContext, get_course_discussion_settings, set_course_discussion_settings
 from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
-from openedx.core.djangoapps.monitoring_utils import function_trace
 from student.models import CourseEnrollment
 from util.json_request import JsonResponse, expect_json
 from xmodule.modulestore.django import modulestore
diff --git a/lms/djangoapps/grades/tasks.py b/lms/djangoapps/grades/tasks.py
index 8b59238a4b392720f545bbbe11676dd0a85034ac..3542acb4fcfffe596bb806c700be5d3cd0b36d75 100644
--- a/lms/djangoapps/grades/tasks.py
+++ b/lms/djangoapps/grades/tasks.py
@@ -12,11 +12,12 @@ from django.conf import settings
 from django.contrib.auth.models import User
 from django.core.exceptions import ValidationError
 from django.db.utils import DatabaseError
+from edx_django_utils.monitoring import set_custom_metric, set_custom_metrics_for_course_key
+
 from lms.djangoapps.course_blocks.api import get_course_blocks
 from lms.djangoapps.grades.config.models import ComputeGradesSetting
 from opaque_keys.edx.keys import CourseKey, UsageKey
 from opaque_keys.edx.locator import CourseLocator
-from openedx.core.djangoapps.monitoring_utils import set_custom_metric, set_custom_metrics_for_course_key
 from student.models import CourseEnrollment
 from submissions import api as sub_api
 from track.event_transaction_utils import set_event_transaction_id, set_event_transaction_type
diff --git a/lms/envs/common.py b/lms/envs/common.py
index 75bc60b2e41e9f625c53db13d981341a69e032ba..4e7afd9d30fd1390bbfd1bf268a33c0e8f19bc17 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -1216,11 +1216,12 @@ CREDIT_NOTIFICATION_CACHE_TIMEOUT = 5 * 60 * 60
 MIDDLEWARE_CLASSES = [
     'crum.CurrentRequestUserMiddleware',
 
-    # Clears request cache. This is a safer request cache.
-    'edx_django_utils.cache.middleware.RequestCacheMiddleware',
-
+    # Deprecated, but well entrenched RequestCache
     'openedx.core.djangoapps.request_cache.middleware.RequestCache',
-    'openedx.core.djangoapps.monitoring_utils.middleware.MonitoringCustomMetrics',
+
+    # A newer and safer request cache.
+    'edx_django_utils.cache.middleware.RequestCacheMiddleware',
+    'edx_django_utils.monitoring.middleware.MonitoringCustomMetricsMiddleware',
 
     'mobile_api.middleware.AppVersionUpgrade',
     'openedx.core.djangoapps.header_control.middleware.HeaderControlMiddleware',
diff --git a/openedx/core/djangoapps/monitoring_utils/__init__.py b/openedx/core/djangoapps/monitoring_utils/__init__.py
deleted file mode 100644
index ed653274786b11beeabc030f3bbb3ad8cf06db97..0000000000000000000000000000000000000000
--- a/openedx/core/djangoapps/monitoring_utils/__init__.py
+++ /dev/null
@@ -1,112 +0,0 @@
-"""
-This is an interface to the monitoring_utils middleware.  Functions
-defined in this module can be used to report monitoring custom metrics.
-
-Usage:
-
-    from openedx.core.djangoapps import monitoring_utils
-    ...
-    monitoring_utils.accumulate('xb_user_state.get_many.num_items', 4)
-
-There is no need to do anything else.  The metrics are automatically cleared
-before the next request.
-
-We try to keep track of our custom metrics at:
-
-https://openedx.atlassian.net/wiki/display/PERF/Custom+Metrics+in+New+Relic
-
-At this time, these custom metrics will only be reported to New Relic.
-
-TODO: supply additional public functions for storing strings and booleans.
-
-"""
-from contextlib import contextmanager
-
-from . import middleware
-try:
-    import newrelic.agent
-except ImportError:
-    newrelic = None  # pylint: disable=invalid-name
-
-
-def accumulate(name, value):
-    """
-    Accumulate monitoring custom metric for the current request.
-
-    The named metric is accumulated by a numerical amount using the sum.  All
-    metrics are queued up in the request_cache for this request.  At the end of
-    the request, the monitoring_utils middleware will batch report all
-    queued accumulated metrics to the monitoring tool (e.g. New Relic).
-
-    Arguments:
-        name (str): The metric name.  It should be period-delimited, and
-            increase in specificity from left to right.  For example:
-            'xb_user_state.get_many.num_items'.
-        value (number):  The amount to accumulate into the named metric.  When
-            accumulate() is called multiple times for a given metric name
-            during a request, the sum of the values for each call is reported
-            for that metric.  For metrics which don't make sense to accumulate,
-            make sure to only call this function once during a request.
-    """
-    middleware.MonitoringCustomMetrics.accumulate_metric(name, value)
-
-
-def increment(name):
-    """
-    Increment a monitoring custom metric representing a counter.
-
-    Here we simply accumulate a new custom metric with a value of 1, and the
-    middleware should automatically aggregate this metric.
-    """
-    accumulate(name, 1)
-
-
-def set_custom_metrics_for_course_key(course_key):
-    """
-    Set monitoring custom metrics related to a course key.
-
-    This is not cached, and only support reporting to New Relic Insights.
-
-    """
-    if not newrelic:
-        return
-    newrelic.agent.add_custom_parameter('course_id', unicode(course_key))
-    newrelic.agent.add_custom_parameter('org', unicode(course_key.org))
-
-
-def set_custom_metric(key, value):
-    """
-    Set monitoring custom metric.
-
-    This is not cached, and only support reporting to New Relic Insights.
-
-    """
-    if not newrelic:
-        return
-    newrelic.agent.add_custom_parameter(key, value)
-
-
-def set_monitoring_transaction_name(name, group=None, priority=None):
-    """
-    Sets the transaction name for monitoring.
-
-    This is not cached, and only support reporting to New Relic.
-
-    """
-    if not newrelic:
-        return
-    newrelic.agent.set_transaction_name(name, group, priority)
-
-
-@contextmanager
-def function_trace(function_name):
-    """
-    Wraps a chunk of code that we want to appear as a separate, explicit,
-    segment in our monitoring tools.
-    """
-    if newrelic:
-        nr_transaction = newrelic.agent.current_transaction()
-        with newrelic.agent.FunctionTrace(nr_transaction, function_name):
-            yield
-    else:
-        yield
diff --git a/openedx/core/djangoapps/monitoring_utils/middleware.py b/openedx/core/djangoapps/monitoring_utils/middleware.py
deleted file mode 100644
index 433f31be4c36cacd5ae1a5924aa2a40ce7be9e83..0000000000000000000000000000000000000000
--- a/openedx/core/djangoapps/monitoring_utils/middleware.py
+++ /dev/null
@@ -1,175 +0,0 @@
-"""
-Middleware for handling the storage, aggregation, and reporting of custom
-metrics for monitoring.
-
-At this time, the custom metrics can only be reported to New Relic.
-
-This middleware will only call on the newrelic agent if there are any metrics
-to report for this request, so it will not incur any processing overhead for
-request handlers which do not record custom metrics.
-
-"""
-import logging
-from uuid import uuid4
-
-import psutil
-
-from openedx.core.djangoapps.request_cache import get_cache
-from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace
-
-log = logging.getLogger(__name__)
-try:
-    import newrelic.agent
-except ImportError:
-    log.warning("Unable to load NewRelic agent module")
-    newrelic = None  # pylint: disable=invalid-name
-
-
-REQUEST_CACHE_KEY = 'monitoring_custom_metrics'
-WAFFLE_NAMESPACE = 'monitoring_utils'
-
-
-class MonitoringCustomMetrics(object):
-    """
-    The middleware class.  Make sure to add below the request cache in
-    MIDDLEWARE_CLASSES.
-    """
-
-    @classmethod
-    def _get_metrics_cache(cls):
-        """
-        Get a reference to the part of the request cache wherein we store New
-        Relic custom metrics related to the current request.
-        """
-        return get_cache(name=REQUEST_CACHE_KEY)
-
-    @classmethod
-    def accumulate_metric(cls, name, value):
-        """
-        Accumulate a custom metric (name and value) in the metrics cache.
-        """
-        metrics_cache = cls._get_metrics_cache()
-        metrics_cache.setdefault(name, 0)
-        metrics_cache[name] += value
-
-    @classmethod
-    def _batch_report(cls):
-        """
-        Report the collected custom metrics to New Relic.
-        """
-        if not newrelic:
-            return
-        metrics_cache = cls._get_metrics_cache()
-        for metric_name, metric_value in metrics_cache.iteritems():
-            newrelic.agent.add_custom_parameter(metric_name, metric_value)
-
-    # Whether or not there was an exception, report any custom NR metrics that
-    # may have been collected.
-
-    def process_response(self, request, response):  # pylint: disable=unused-argument
-        """
-        Django middleware handler to process a response
-        """
-        self._batch_report()
-        return response
-
-    def process_exception(self, request, exception):  # pylint: disable=unused-argument
-        """
-        Django middleware handler to process an exception
-        """
-        self._batch_report()
-        return None
-
-
-class MonitoringMemoryMiddleware(object):
-    """
-    Middleware for monitoring memory usage.
-    """
-    memory_data_key = u'memory_data'
-    guid_key = u'guid_key'
-
-    def process_request(self, request):
-        if self._is_enabled():
-            self._cache[self.guid_key] = unicode(uuid4())
-            log_prefix = self._log_prefix(u"Before", request)
-            self._cache[self.memory_data_key] = self._memory_data(log_prefix)
-
-    def process_response(self, request, response):
-        if self._is_enabled():
-            log_prefix = self._log_prefix(u"After", request)
-            new_memory_data = self._memory_data(log_prefix)
-
-            log_prefix = self._log_prefix(u"Diff", request)
-            self._log_diff_memory_data(log_prefix, new_memory_data, self._cache.get(self.memory_data_key))
-        return response
-
-    @property
-    def _cache(self):
-        """
-        Namespaced request cache for tracking memory usage.
-        """
-        return get_cache(name='monitoring_memory')
-
-    def _log_prefix(self, prefix, request):
-        """
-        Returns a formatted prefix for logging for the given request.
-        """
-        # After a celery task runs, the request cache is cleared. So if celery
-        # tasks are running synchronously (CELERY_ALWAYS _EAGER), "guid_key"
-        # will no longer be in the request cache when process_response executes.
-        cached_guid = self._cache.get(self.guid_key) or u"without_guid"
-        return u"{} request '{} {} {}'".format(prefix, request.method, request.path, cached_guid)
-
-    def _memory_data(self, log_prefix):
-        """
-        Returns a dict with information for current memory utilization.
-        Uses log_prefix in log statements.
-        """
-        machine_data = psutil.virtual_memory()
-
-        process = psutil.Process()
-        process_data = {
-            'memory_info': process.get_memory_info(),
-            'ext_memory_info': process.get_ext_memory_info(),
-            'memory_percent': process.get_memory_percent(),
-            'cpu_percent': process.get_cpu_percent(),
-        }
-
-        log.info(u"%s Machine memory usage: %s; Process memory usage: %s", log_prefix, machine_data, process_data)
-        return {
-            'machine_data': machine_data,
-            'process_data': process_data,
-        }
-
-    def _log_diff_memory_data(self, prefix, new_memory_data, old_memory_data):
-        """
-        Computes and logs the difference in memory utilization
-        between the given old and new memory data.
-        """
-        def _vmem_used(memory_data):
-            return memory_data['machine_data'].used
-
-        def _process_mem_percent(memory_data):
-            return memory_data['process_data']['memory_percent']
-
-        def _process_rss(memory_data):
-            return memory_data['process_data']['memory_info'].rss
-
-        def _process_vms(memory_data):
-            return memory_data['process_data']['memory_info'].vms
-
-        if new_memory_data and old_memory_data:
-            log.info(
-                u"%s Diff Vmem used: %s, Diff percent memory: %s, Diff rss: %s, Diff vms: %s",
-                prefix,
-                _vmem_used(new_memory_data) - _vmem_used(old_memory_data),
-                _process_mem_percent(new_memory_data) - _process_mem_percent(old_memory_data),
-                _process_rss(new_memory_data) - _process_rss(old_memory_data),
-                _process_vms(new_memory_data) - _process_vms(old_memory_data),
-            )
-
-    def _is_enabled(self):
-        """
-        Returns whether this middleware is enabled.
-        """
-        return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE).is_enabled(u'enable_memory_middleware')
diff --git a/openedx/core/djangoapps/monitoring_utils/tests.py b/openedx/core/djangoapps/monitoring_utils/tests.py
deleted file mode 100644
index 16763b45e8bd054d980da5e03aaadda4bad5148c..0000000000000000000000000000000000000000
--- a/openedx/core/djangoapps/monitoring_utils/tests.py
+++ /dev/null
@@ -1,47 +0,0 @@
-"""
-Tests for monitoring custom metrics.
-"""
-from django.test import TestCase
-from mock import call, patch
-
-from openedx.core.djangoapps import monitoring_utils
-from openedx.core.djangoapps.monitoring_utils.middleware import MonitoringCustomMetrics
-
-
-class TestMonitoringCustomMetrics(TestCase):
-    """
-    Test the monitoring_utils middleware and helpers
-    """
-
-    @patch('newrelic.agent')
-    def test_custom_metrics_with_new_relic(self, mock_newrelic_agent):
-        """
-        Test normal usage of collecting custom metrics and reporting to New Relic
-        """
-        monitoring_utils.accumulate('hello', 10)
-        monitoring_utils.accumulate('world', 10)
-        monitoring_utils.accumulate('world', 10)
-        monitoring_utils.increment('foo')
-        monitoring_utils.increment('foo')
-
-        # based on the metric data above, we expect the following calls to newrelic:
-        nr_agent_calls_expected = [
-            call('hello', 10),
-            call('world', 20),
-            call('foo', 2),
-        ]
-
-        # fake a response to trigger metrics reporting
-        MonitoringCustomMetrics().process_response(
-            'fake request',
-            'fake response',
-        )
-
-        # Assert call counts to newrelic.agent.add_custom_parameter()
-        expected_call_count = len(nr_agent_calls_expected)
-        measured_call_count = mock_newrelic_agent.add_custom_parameter.call_count
-        self.assertEqual(expected_call_count, measured_call_count)
-
-        # Assert call args to newrelic.agent.add_custom_parameter().  Due to
-        # the nature of python dicts, call order is undefined.
-        mock_newrelic_agent.add_custom_parameter.has_calls(nr_agent_calls_expected, any_order=True)
diff --git a/openedx/core/djangoapps/oauth_dispatch/tests/test_views.py b/openedx/core/djangoapps/oauth_dispatch/tests/test_views.py
index 098980b46002bf2ce7bbe275c414849597b1def8..312e0e5e15705ae31a30ffc210b56b595510bd53 100644
--- a/openedx/core/djangoapps/oauth_dispatch/tests/test_views.py
+++ b/openedx/core/djangoapps/oauth_dispatch/tests/test_views.py
@@ -235,7 +235,7 @@ class TestAccessTokenView(AccessTokenLoginMixin, mixins.AccessTokenMixin, _Dispa
         (None, 'no_token_type_supplied'),
     )
     @ddt.unpack
-    @patch('openedx.core.djangoapps.monitoring_utils.set_custom_metric')
+    @patch('edx_django_utils.monitoring.set_custom_metric')
     def test_access_token_metrics(self, token_type, expected_token_type, mock_set_custom_metric):
         response = self._post_request(self.user, self.dot_app, token_type=token_type)
         self.assertEqual(response.status_code, 200)
@@ -245,7 +245,7 @@ class TestAccessTokenView(AccessTokenLoginMixin, mixins.AccessTokenMixin, _Dispa
         ]
         mock_set_custom_metric.assert_has_calls(expected_calls, any_order=True)
 
-    @patch('openedx.core.djangoapps.monitoring_utils.set_custom_metric')
+    @patch('edx_django_utils.monitoring.set_custom_metric')
     def test_access_token_metrics_for_bad_request(self, mock_set_custom_metric):
         grant_type = dot_models.Application.GRANT_PASSWORD
         invalid_body = {
@@ -596,13 +596,13 @@ class TestViewDispatch(TestCase):
         ]
         mock_set_custom_metric.assert_has_calls(expected_calls, any_order=True)
 
-    @patch('openedx.core.djangoapps.monitoring_utils.set_custom_metric')
+    @patch('edx_django_utils.monitoring.set_custom_metric')
     def test_dispatching_post_to_dot(self, mock_set_custom_metric):
         request = self._post_request('dot-id')
         self.assertEqual(self.view.select_backend(request), self.dot_adapter.backend)
         self._verify_oauth_metrics_calls(mock_set_custom_metric, 'dot')
 
-    @patch('openedx.core.djangoapps.monitoring_utils.set_custom_metric')
+    @patch('edx_django_utils.monitoring.set_custom_metric')
     def test_dispatching_post_to_dop(self, mock_set_custom_metric):
         request = self._post_request('dop-id')
         self.assertEqual(self.view.select_backend(request), self.dop_adapter.backend)
diff --git a/openedx/core/djangoapps/oauth_dispatch/views.py b/openedx/core/djangoapps/oauth_dispatch/views.py
index 65df22d39b58ab896ba629635ea3fe801d771a8f..0918528f31052a8cc58808f31991aad0f41075fe 100644
--- a/openedx/core/djangoapps/oauth_dispatch/views.py
+++ b/openedx/core/djangoapps/oauth_dispatch/views.py
@@ -10,13 +10,13 @@ import logging
 
 from django.conf import settings
 from django.views.generic import View
+from edx_django_utils import monitoring as monitoring_utils
 from edx_oauth2_provider import views as dop_views  # django-oauth2-provider views
 from oauth2_provider import models as dot_models  # django-oauth-toolkit
 from oauth2_provider import views as dot_views
 from ratelimit import ALL
 from ratelimit.mixins import RatelimitMixin
 
-from openedx.core.djangoapps import monitoring_utils
 from openedx.core.djangoapps.auth_exchange import views as auth_exchange_views
 from openedx.core.lib.token_utils import JwtBuilder
 
diff --git a/openedx/core/djangoapps/schedules/resolvers.py b/openedx/core/djangoapps/schedules/resolvers.py
index 59c056e22bbb6c64dbc281014c02654247c7bd40..1fad58c654e6eaab04bca830227c16309701dd87 100644
--- a/openedx/core/djangoapps/schedules/resolvers.py
+++ b/openedx/core/djangoapps/schedules/resolvers.py
@@ -8,12 +8,11 @@ from django.contrib.auth.models import User
 from django.contrib.staticfiles.templatetags.staticfiles import static
 from django.urls import reverse
 from django.db.models import F, Q
-
 from edx_ace.recipient_resolver import RecipientResolver
 from edx_ace.recipient import Recipient
+from edx_django_utils.monitoring import function_trace, set_custom_metric
 
 from courseware.date_summary import verified_upgrade_deadline_link, verified_upgrade_link_is_valid
-from openedx.core.djangoapps.monitoring_utils import function_trace, set_custom_metric
 from openedx.core.djangoapps.schedules.content_highlights import get_week_highlights
 from openedx.core.djangoapps.schedules.exceptions import CourseUpdateDoesNotExist
 from openedx.core.djangoapps.schedules.models import Schedule, ScheduleExperience
diff --git a/openedx/core/djangoapps/schedules/tasks.py b/openedx/core/djangoapps/schedules/tasks.py
index 08b11dc46d1f8383e0fcf2cbe1388f827738256a..24a43ae59f1720ac8cd36bec4e8572bfc3dcf6cd 100644
--- a/openedx/core/djangoapps/schedules/tasks.py
+++ b/openedx/core/djangoapps/schedules/tasks.py
@@ -15,9 +15,9 @@ from celery_utils.persist_on_failure import LoggedPersistOnFailureTask
 from edx_ace import ace
 from edx_ace.message import Message
 from edx_ace.utils.date import deserialize, serialize
+from edx_django_utils.monitoring import set_custom_metric
 from opaque_keys.edx.keys import CourseKey
 
-from openedx.core.djangoapps.monitoring_utils import set_custom_metric
 from openedx.core.djangoapps.schedules import message_types
 from openedx.core.djangoapps.schedules.models import Schedule, ScheduleConfig
 from openedx.core.djangoapps.schedules import resolvers
diff --git a/openedx/core/djangolib/testing/utils.py b/openedx/core/djangolib/testing/utils.py
index 769fdb238c1ac12fd6f1b5623ed3d7dc037f4b2e..f4359002c34d84482b5cdeb88704de8c74bfba65 100644
--- a/openedx/core/djangolib/testing/utils.py
+++ b/openedx/core/djangolib/testing/utils.py
@@ -19,7 +19,9 @@ from django.core.cache import caches
 from django.db import DEFAULT_DB_ALIAS, connections
 from django.test import RequestFactory, TestCase, override_settings
 from django.test.utils import CaptureQueriesContext
-from openedx.core.djangoapps.request_cache.middleware import RequestCache
+from edx_django_utils.cache import RequestCache
+
+from openedx.core.djangoapps.request_cache.middleware import RequestCache as DeprecatedRequestCache
 
 
 class CacheIsolationMixin(object):
@@ -118,7 +120,8 @@ class CacheIsolationMixin(object):
         # Clear that.
         sites.models.SITE_CACHE.clear()
 
-        RequestCache.clear_request_cache()
+        DeprecatedRequestCache.clear_request_cache()
+        RequestCache.clear_all_namespaces()
 
 
 class CacheIsolationTestCase(CacheIsolationMixin, TestCase):
diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt
index c09da2848104309380500c587c7640bb03a7cdb1..0ab9061e7ef9518bfe8118486f1847c2cd0038f1 100644
--- a/requirements/edx/base.txt
+++ b/requirements/edx/base.txt
@@ -115,7 +115,7 @@ edx-completion==0.1.8
 edx-django-oauth2-provider==1.3.4
 edx-django-release-util==0.3.1
 edx-django-sites-extensions==2.3.1
-edx-django-utils==0.4.1
+edx-django-utils==0.5.1
 edx-drf-extensions==1.6.1
 edx-enterprise==0.72.5
 edx-i18n-tools==0.4.6
diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt
index a6477011758ce9b92b36dc2fe3d376aae5c406a7..1a1e6c12a4bd1eaa547c788b700d8b0a4192fba7 100644
--- a/requirements/edx/development.txt
+++ b/requirements/edx/development.txt
@@ -135,7 +135,7 @@ edx-completion==0.1.8
 edx-django-oauth2-provider==1.3.4
 edx-django-release-util==0.3.1
 edx-django-sites-extensions==2.3.1
-edx-django-utils==0.4.1
+edx-django-utils==0.5.1
 edx-drf-extensions==1.6.1
 edx-enterprise==0.72.5
 edx-i18n-tools==0.4.6
diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt
index 1b9c4d662d47c32ffee3bf89b233cfab05de8bbf..0f4f6027a0f8f3acd9680b104b6cdd9e048bc4f8 100644
--- a/requirements/edx/testing.txt
+++ b/requirements/edx/testing.txt
@@ -130,7 +130,7 @@ edx-completion==0.1.8
 edx-django-oauth2-provider==1.3.4
 edx-django-release-util==0.3.1
 edx-django-sites-extensions==2.3.1
-edx-django-utils==0.4.1
+edx-django-utils==0.5.1
 edx-drf-extensions==1.6.1
 edx-enterprise==0.72.5
 edx-i18n-tools==0.4.6