diff --git a/cms/envs/common.py b/cms/envs/common.py
index af161418c67856f8b12668bc937d660451119dbd..05a3b84e15c7a9ed65544d035e83af65f3eb2170 100644
--- a/cms/envs/common.py
+++ b/cms/envs/common.py
@@ -2287,6 +2287,9 @@ DISABLE_DEPRECATED_SIGNUP_URL = False
 ##### LOGISTRATION RATE LIMIT SETTINGS #####
 LOGISTRATION_RATELIMIT_RATE = '100/5m'
 
+##### REGISTRATION RATE LIMIT SETTINGS #####
+REGISTRATION_VALIDATION_RATELIMIT = '30/7d'
+
 ##### PASSWORD RESET RATE LIMIT SETTINGS #####
 PASSWORD_RESET_IP_RATE = '1/m'
 PASSWORD_RESET_EMAIL_RATE = '2/h'
diff --git a/cms/envs/production.py b/cms/envs/production.py
index e0baad585f1bb35b8141ae18bdc2a226f51234fd..2df0b7f334b2bf56491518bace66178f848a066f 100644
--- a/cms/envs/production.py
+++ b/cms/envs/production.py
@@ -267,6 +267,11 @@ COMPREHENSIVE_THEME_LOCALE_PATHS = ENV_TOKENS.get('COMPREHENSIVE_THEME_LOCALE_PA
 #Timezone overrides
 TIME_ZONE = ENV_TOKENS.get('CELERY_TIMEZONE', CELERY_TIMEZONE)
 
+##### REGISTRATION RATE LIMIT SETTINGS #####
+REGISTRATION_VALIDATION_RATELIMIT = ENV_TOKENS.get(
+    'REGISTRATION_VALIDATION_RATELIMIT', REGISTRATION_VALIDATION_RATELIMIT
+)
+
 # Push to LMS overrides
 GIT_REPO_EXPORT_DIR = ENV_TOKENS.get('GIT_REPO_EXPORT_DIR', '/edx/var/edxapp/export_course_repos')
 
diff --git a/cms/envs/test.py b/cms/envs/test.py
index d6bd389537492c85d9e6b694fe8631ad171e4288..3c63dd8dc5f43f962d5ee7adbf7dc17c6c031917 100644
--- a/cms/envs/test.py
+++ b/cms/envs/test.py
@@ -305,3 +305,5 @@ PROCTORING_SETTINGS = {}
 
 ##### LOGISTRATION RATE LIMIT SETTINGS #####
 LOGISTRATION_RATELIMIT_RATE = '5/5m'
+
+REGISTRATION_VALIDATION_RATELIMIT = '5/minute'
diff --git a/lms/envs/common.py b/lms/envs/common.py
index 9554ce9e7653ee68c6d5e66476c2f0279c9991dd..d8a8a1a37e4ae9083ad750f9c14fec60e6821c57 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -2575,6 +2575,8 @@ REST_FRAMEWORK = {
     },
 }
 
+REGISTRATION_VALIDATION_RATELIMIT = '30/7d'
+
 SWAGGER_SETTINGS = {
     'DEFAULT_INFO': 'openedx.core.apidocs.api_info',
 }
diff --git a/lms/envs/production.py b/lms/envs/production.py
index 5479e412bf3f76c52e4d1ea6e383fab9aa8386b3..d855dc7d45dfbea44326e5f99904947b64119285 100644
--- a/lms/envs/production.py
+++ b/lms/envs/production.py
@@ -603,6 +603,11 @@ MAX_FAILED_LOGIN_ATTEMPTS_LOCKOUT_PERIOD_SECS = ENV_TOKENS.get(
 ##### LOGISTRATION RATE LIMIT SETTINGS #####
 LOGISTRATION_RATELIMIT_RATE = ENV_TOKENS.get('LOGISTRATION_RATELIMIT_RATE', LOGISTRATION_RATELIMIT_RATE)
 
+##### REGISTRATION RATE LIMIT SETTINGS #####
+REGISTRATION_VALIDATION_RATELIMIT = ENV_TOKENS.get(
+    'REGISTRATION_VALIDATION_RATELIMIT', REGISTRATION_VALIDATION_RATELIMIT
+)
+
 #### PASSWORD POLICY SETTINGS #####
 AUTH_PASSWORD_VALIDATORS = ENV_TOKENS.get("AUTH_PASSWORD_VALIDATORS", AUTH_PASSWORD_VALIDATORS)
 
diff --git a/lms/envs/test.py b/lms/envs/test.py
index 3fa29ba538e8b7d3610744d78eb879558808ccf9..f633e68e8c8af76c5c74a7f3f0a2baecc0330402 100644
--- a/lms/envs/test.py
+++ b/lms/envs/test.py
@@ -518,11 +518,6 @@ ACTIVATION_EMAIL_FROM_ADDRESS = 'test_activate@edx.org'
 
 TEMPLATES[0]['OPTIONS']['debug'] = True
 
-########################### DRF default throttle rates ############################
-# Increasing rates to enable test cases hitting registration view succesfully.
-# Lower rate is causing view to get blocked, causing test case failure.
-REST_FRAMEWORK['DEFAULT_THROTTLE_RATES']['registration_validation'] = '100/minute'
-
 ########################## VIDEO TRANSCRIPTS STORAGE ############################
 VIDEO_TRANSCRIPTS_SETTINGS = dict(
     VIDEO_TRANSCRIPTS_MAX_BYTES=3 * 1024 * 1024,    # 3 MB
@@ -603,3 +598,5 @@ RATELIMIT_RATE = '2/m'
 
 ##### LOGISTRATION RATE LIMIT SETTINGS #####
 LOGISTRATION_RATELIMIT_RATE = '5/5m'
+
+REGISTRATION_VALIDATION_RATELIMIT = '5/minute'
diff --git a/openedx/core/djangoapps/user_authn/views/register.py b/openedx/core/djangoapps/user_authn/views/register.py
index bfc454f30381b2ea87713ff5b66a2a631dac764e..0d19bdfd4dd8527f07e88688a5f14e978cd5b639 100644
--- a/openedx/core/djangoapps/user_authn/views/register.py
+++ b/openedx/core/djangoapps/user_authn/views/register.py
@@ -15,19 +15,20 @@ from django.core.validators import ValidationError
 from django.db import transaction
 from django.dispatch import Signal
 from django.http import HttpResponse, HttpResponseForbidden
-from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie
-from django.views.decorators.debug import sensitive_post_parameters
 from django.urls import reverse
 from django.utils.decorators import method_decorator
 from django.utils.translation import get_language
 from django.utils.translation import ugettext as _
+from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie
+from django.views.decorators.debug import sensitive_post_parameters
+from ipware.ip import get_ip
 from pytz import UTC
+from ratelimit.decorators import ratelimit
 from requests import HTTPError
-from six import text_type
-from ipware.ip import get_ip
 from rest_framework.response import Response
 from rest_framework.throttling import AnonRateThrottle
 from rest_framework.views import APIView
+from six import text_type
 from social_core.exceptions import AuthAlreadyAssociated, AuthException
 from social_django import utils as social_utils
 
@@ -48,27 +49,27 @@ from openedx.core.djangoapps.user_api.accounts.api import (
     get_username_existence_validation_error,
     get_username_validation_error
 )
-from openedx.core.djangoapps.user_authn.utils import generate_password, is_registration_api_v1
 from openedx.core.djangoapps.user_api.preferences import api as preferences_api
 from openedx.core.djangoapps.user_authn.cookies import set_logged_in_cookies
+from openedx.core.djangoapps.user_authn.utils import generate_password, is_registration_api_v1
 from openedx.core.djangoapps.user_authn.views.registration_form import (
-    get_registration_extension_form,
     AccountCreationForm,
-    RegistrationFormFactory
+    RegistrationFormFactory,
+    get_registration_extension_form
 )
 from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace
 from student.helpers import (
+    AccountValidationError,
     authenticate_new_user,
     create_or_set_user_attribute_created_on_site,
-    do_create_account,
-    AccountValidationError,
+    do_create_account
 )
 from student.models import (
     RegistrationCookieConfiguration,
     UserAttribute,
     create_comments_service_user,
     email_exists_or_retired,
-    username_exists_or_retired,
+    username_exists_or_retired
 )
 from student.views import compose_and_send_activation_email
 from third_party_auth import pipeline, provider
@@ -110,6 +111,7 @@ REGISTRATION_FAILURE_LOGGING_FLAG = WaffleFlag(
     waffle_namespace=WaffleFlagNamespace(name=u'registration'),
     flag_name=u'enable_failure_logging',
 )
+REAL_IP_KEY = 'openedx.core.djangoapps.util.ratelimit.real_ip'
 
 
 @transaction.non_atomic_requests
@@ -575,19 +577,6 @@ class RegistrationView(APIView):
             pass
 
 
-class RegistrationValidationThrottle(AnonRateThrottle):
-    """
-    Custom throttle rate for /api/user/v1/validation/registration
-    endpoint's use case.
-    """
-
-    scope = 'registration_validation'
-
-    def get_ident(self, request):
-        client_ip = get_ip(request)
-        return client_ip
-
-
 # pylint: disable=line-too-long
 class RegistrationValidationView(APIView):
     """
@@ -677,7 +666,6 @@ class RegistrationValidationView(APIView):
 
     # This end-point is available to anonymous users, so no authentication is needed.
     authentication_classes = []
-    throttle_classes = (RegistrationValidationThrottle,)
 
     def name_handler(self, request):
         name = request.data.get('name')
@@ -725,6 +713,9 @@ class RegistrationValidationView(APIView):
         "country": country_handler
     }
 
+    @method_decorator(
+        ratelimit(key=REAL_IP_KEY, rate=settings.REGISTRATION_VALIDATION_RATELIMIT, method='POST', block=True)
+    )
     def post(self, request):
         """
         POST /api/user/v1/validation/registration/
diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_register.py b/openedx/core/djangoapps/user_authn/views/tests/test_register.py
index 4a0d7f7a54f33fc0ed4394e672565d9e7a2fd2b5..86b044aa216b2bdeef2d6ce9744b48c6a2555d78 100644
--- a/openedx/core/djangoapps/user_authn/views/tests/test_register.py
+++ b/openedx/core/djangoapps/user_authn/views/tests/test_register.py
@@ -2,24 +2,23 @@
 """Tests for account creation"""
 
 import json
-from unittest import skipIf, skipUnless
 from datetime import datetime
+from unittest import skipIf, skipUnless
 
 import ddt
 import httpretty
 import mock
 import six
-from six.moves import range
-
 from django.conf import settings
 from django.contrib.auth.models import User
 from django.core import mail
+from django.core.cache import cache
 from django.test import TransactionTestCase
 from django.test.client import RequestFactory
 from django.test.utils import override_settings
 from django.urls import reverse
 from pytz import UTC
-
+from six.moves import range
 from social_django.models import Partial, UserSocialAuth
 
 from openedx.core.djangoapps.site_configuration.helpers import get_value
@@ -32,25 +31,24 @@ from openedx.core.djangoapps.user_api.accounts import (
     EMAIL_MIN_LENGTH,
     NAME_MAX_LENGTH,
     REQUIRED_FIELD_CONFIRM_EMAIL_MSG,
-    USERNAME_MAX_LENGTH,
-    USERNAME_MIN_LENGTH,
     USERNAME_BAD_LENGTH_MSG,
     USERNAME_CONFLICT_MSG,
     USERNAME_INVALID_CHARS_ASCII,
     USERNAME_INVALID_CHARS_UNICODE,
+    USERNAME_MAX_LENGTH,
+    USERNAME_MIN_LENGTH
 )
 from openedx.core.djangoapps.user_api.accounts.api import get_account_settings
 from openedx.core.djangoapps.user_api.accounts.tests import testutils
 from openedx.core.djangoapps.user_api.accounts.tests.retirement_helpers import (  # pylint: disable=unused-import
     RetirementTestCase,
     fake_requested_retirement,
-    setup_retirement_states,
+    setup_retirement_states
 )
-from openedx.core.djangoapps.user_api.tests.test_helpers import TestCaseForm
 from openedx.core.djangoapps.user_api.tests.test_constants import SORTED_COUNTRIES
+from openedx.core.djangoapps.user_api.tests.test_helpers import TestCaseForm
 from openedx.core.djangoapps.user_api.tests.test_views import UserAPITestCase
-from openedx.core.djangoapps.user_authn.views.register import RegistrationValidationThrottle, \
-    REGISTRATION_FAILURE_LOGGING_FLAG
+from openedx.core.djangoapps.user_authn.views.register import REGISTRATION_FAILURE_LOGGING_FLAG
 from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag
 from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
 from openedx.core.lib.api import test_utils
@@ -2098,6 +2096,10 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase):
     endpoint_name = 'registration_validation'
     path = reverse(endpoint_name)
 
+    def setUp(self):
+        super(RegistrationValidationViewTests, self).setUp()
+        cache.clear()
+
     def get_validation_decision(self, data):
         response = self.client.post(self.path, data)
         return response.data.get('validation_decisions', {})
@@ -2297,7 +2299,8 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase):
         to enforce limits; that's why this test needs a "real"
         default cache (as opposed to the usual-for-tests DummyCache)
         """
-        for _ in range(RegistrationValidationThrottle().num_requests):
-            self.request_without_auth('post', self.path)
+        for _ in range(int(settings.REGISTRATION_VALIDATION_RATELIMIT.split('/')[0])):
+            response = self.request_without_auth('post', self.path)
+            self.assertNotEqual(response.status_code, 403)
         response = self.request_without_auth('post', self.path)
-        self.assertEqual(response.status_code, 429)
+        self.assertEqual(response.status_code, 403)