diff --git a/common/djangoapps/student/management/commands/create_user.py b/common/djangoapps/student/management/commands/create_user.py
index d375dedc54a39e6167a3e53e7630e7094f79f8e0..cacc5dea8ea99b691d2176a0a61f127c9c394483 100644
--- a/common/djangoapps/student/management/commands/create_user.py
+++ b/common/djangoapps/student/management/commands/create_user.py
@@ -1,7 +1,7 @@
 from optparse import make_option
 from django.core.management.base import BaseCommand
-from student.models import CourseEnrollment, Registration
-from student.views import _do_create_account
+from student.models import CourseEnrollment, Registration, create_comments_service_user
+from student.views import _do_create_account, AccountValidationError
 from django.contrib.auth.models import User
 
 from track.management.tracked_command import TrackedCommand
@@ -74,17 +74,16 @@ class Command(TrackedCommand):
             'honor_code': u'true',
             'terms_of_service': u'true',
         }
-        create_account = _do_create_account(post_data)
-        if isinstance(create_account, tuple):
-            user = create_account[0]
+        try:
+            user, profile, reg = _do_create_account(post_data)
             if options['staff']:
                 user.is_staff = True
                 user.save()
-            reg = Registration.objects.get(user=user)
             reg.activate()
             reg.save()
-        else:
-            print create_account
+            create_comments_service_user(user)
+        except AccountValidationError as e:
+            print e.message
             user = User.objects.get(email=options['email'])
         if options['course']:
             CourseEnrollment.enroll(user, options['course'], mode=options['mode'])
diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py
index c2fcdea35472ce94a8318543068ec58abfde0391..8f2952fdfe4c7b65eceed41e6a9958f2cc21f6c7 100644
--- a/common/djangoapps/student/models.py
+++ b/common/djangoapps/student/models.py
@@ -831,18 +831,18 @@ def add_user_to_default_group(user, group):
     utg.save()
 
 
-@receiver(post_save, sender=User)
-def update_user_information(sender, instance, created, **kwargs):
+def create_comments_service_user(user):
     if not settings.FEATURES['ENABLE_DISCUSSION_SERVICE']:
         # Don't try--it won't work, and it will fill the logs with lots of errors
         return
     try:
-        cc_user = cc.User.from_django_user(instance)
+        cc_user = cc.User.from_django_user(user)
         cc_user.save()
     except Exception as e:
         log = logging.getLogger("edx.discussion")
-        log.error(unicode(e))
-        log.error("update user info to discussion failed for user with id: " + str(instance.id))
+        log.error(
+            "Could not create comments service user with id {}".format(user.id),
+            exc_info=True)
 
 # Define login and logout handlers here in the models file, instead of the views file,
 # so that they are more likely to be loaded when a Studio user brings up the Studio admin
diff --git a/common/djangoapps/student/tests/test_create_account.py b/common/djangoapps/student/tests/test_create_account.py
index 1f5f4943063797f09c3c4de6a2d8ef78887d670a..bc9503d1d05c1c4818a4e2dc177d8712d808b4a2 100644
--- a/common/djangoapps/student/tests/test_create_account.py
+++ b/common/djangoapps/student/tests/test_create_account.py
@@ -3,13 +3,17 @@
 import ddt
 from django.contrib.auth.models import User
 from django.core.urlresolvers import reverse
-from django.test import TestCase
+from django.db.transaction import rollback
+from django.test import TestCase, TransactionTestCase
 from django.test.utils import override_settings
 import mock
 
 from user_api.models import UserPreference
 from lang_pref import LANGUAGE_KEY
 
+import student
+
+TEST_CS_URL = 'https://comments.service.test:123/'
 
 @ddt.ddt
 class TestCreateAccount(TestCase):
@@ -41,3 +45,43 @@ class TestCreateAccount(TestCase):
         self.assertEqual(response.status_code, 200)
         user = User.objects.get(username=self.username)
         self.assertEqual(UserPreference.get_preference(user, LANGUAGE_KEY), lang)
+
+
+@mock.patch.dict("student.models.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
+@mock.patch("lms.lib.comment_client.User.base_url", TEST_CS_URL)
+@mock.patch("lms.lib.comment_client.utils.requests.request", return_value=mock.Mock(status_code=200, text='{}'))
+class TestCreateCommentsServiceUser(TransactionTestCase):
+
+    def setUp(self):
+        self.username = "test_user"
+        self.url = reverse("create_account")
+        self.params = {
+            "username": self.username,
+            "email": "test@example.org",
+            "password": "testpass",
+            "name": "Test User",
+            "honor_code": "true",
+            "terms_of_service": "true",
+        }
+
+    def test_cs_user_created(self, request):
+        "If user account creation succeeds, we should create a comments service user"
+        response = self.client.post(self.url, self.params)
+        self.assertEqual(response.status_code, 200)
+        self.assertTrue(request.called)
+        args, kwargs = request.call_args
+        self.assertEqual(args[0], 'put')
+        self.assertTrue(args[1].startswith(TEST_CS_URL))
+        self.assertEqual(kwargs['data']['username'], self.params['username'])
+
+    @mock.patch("student.models.Registration.register", side_effect=Exception)
+    def test_cs_user_not_created(self, register, request):
+        "If user account creation fails, we should not create a comments service user"
+        try:
+            response = self.client.post(self.url, self.params)
+        except:
+            pass
+        with self.assertRaises(User.DoesNotExist):
+            User.objects.get(username=self.username)
+        self.assertTrue(register.called)
+        self.assertFalse(request.called)
diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py
index 61d2aa22d6cc5d9179d3166d32a21c2033d60d92..54f3e2bfb3dbc013a7fda82e982f0dc60f6257d3 100644
--- a/common/djangoapps/student/views.py
+++ b/common/djangoapps/student/views.py
@@ -38,7 +38,8 @@ from course_modes.models import CourseMode
 from student.models import (
     Registration, UserProfile, PendingNameChange,
     PendingEmailChange, CourseEnrollment, unique_id_for_user,
-    CourseEnrollmentAllowed, UserStanding, LoginFailures
+    CourseEnrollmentAllowed, UserStanding, LoginFailures,
+    create_comments_service_user
 )
 from student.forms import PasswordResetFormNoActive
 from student.firebase_token_generator import create_token
@@ -951,6 +952,11 @@ def change_setting(request):
     })
 
 
+class AccountValidationError(Exception):
+    def __init__(self, message, field):
+        super(AccountValidationError, self).__init__(message)
+        self.field = field
+
 def _do_create_account(post_vars):
     """
     Given cleaned post variables, create the User and UserProfile objects, as well as the
@@ -970,19 +976,19 @@ def _do_create_account(post_vars):
     try:
         user.save()
     except IntegrityError:
-        js = {'success': False}
         # Figure out the cause of the integrity error
         if len(User.objects.filter(username=post_vars['username'])) > 0:
-            js['value'] = _("An account with the Public Username '{username}' already exists.").format(username=post_vars['username'])
-            js['field'] = 'username'
-            return JsonResponse(js, status=400)
-
-        if len(User.objects.filter(email=post_vars['email'])) > 0:
-            js['value'] = _("An account with the Email '{email}' already exists.").format(email=post_vars['email'])
-            js['field'] = 'email'
-            return JsonResponse(js, status=400)
-
-        raise
+            raise AccountValidationError(
+                _("An account with the Public Username '{username}' already exists.").format(username=post_vars['username']),
+                field="username"
+                )
+        elif len(User.objects.filter(email=post_vars['email'])) > 0:
+            raise AccountValidationError(
+                _("An account with the Email '{email}' already exists.").format(email=post_vars['email']),
+                field="email"
+                )
+        else:
+            raise
 
     registration.register(user)
 
@@ -1005,6 +1011,7 @@ def _do_create_account(post_vars):
         profile.save()
     except Exception:
         log.exception("UserProfile creation failed for user {id}.".format(id=user.id))
+        raise
 
     UserPreference.set_preference(user, LANGUAGE_KEY, get_language())
 
@@ -1150,11 +1157,17 @@ def create_account(request, post_override=None):
             return JsonResponse(js, status=400)
 
     # Ok, looks like everything is legit.  Create the account.
-    ret = _do_create_account(post_vars)
-    if isinstance(ret, HttpResponse):  # if there was an error then return that
-        return ret
+    try:
+        with transaction.commit_on_success():
+            ret = _do_create_account(post_vars)
+    except AccountValidationError as e:
+        return JsonResponse({'success': False, 'value': e.message, 'field': e.field}, status=400)
+
     (user, profile, registration) = ret
 
+    dog_stats_api.increment("common.student.account_created")
+    create_comments_service_user(user)
+
     context = {
         'name': post_vars['name'],
         'key': registration.activation_key,
@@ -1213,8 +1226,6 @@ def create_account(request, post_override=None):
             login_user.save()
             AUDIT_LOG.info(u"Login activated on extauth account - {0} ({1})".format(login_user.username, login_user.email))
 
-    dog_stats_api.increment("common.student.account_created")
-
     response = JsonResponse({
         'success': True,
         'redirect_url': try_change_enrollment(request),
@@ -1283,20 +1294,16 @@ def auto_auth(request):
 
     # Attempt to create the account.
     # If successful, this will return a tuple containing
-    # the new user object; otherwise it will return an error
-    # message.
-    result = _do_create_account(post_data)
-
-    if isinstance(result, tuple):
-        user = result[0]
-
-    # If we did not create a new account, the user might already
-    # exist.  Attempt to retrieve it.
-    else:
+    # the new user object.
+    try:
+        user, profile, reg = _do_create_account(post_data)
+    except AccountValidationError:
+        # Attempt to retrieve the existing user.
         user = User.objects.get(username=username)
         user.email = email
         user.set_password(password)
         user.save()
+        reg = Registration.objects.get(user=user)
 
     # Set the user's global staff bit
     if is_staff is not None:
@@ -1304,7 +1311,6 @@ def auto_auth(request):
         user.save()
 
     # Activate the user
-    reg = Registration.objects.get(user=user)
     reg.activate()
     reg.save()
 
@@ -1321,6 +1327,8 @@ def auto_auth(request):
     user = authenticate(username=username, password=password)
     login(request, user)
 
+    create_comments_service_user(user)
+
     # Provide the user with a valid CSRF token
     # then return a 200 response
     success_msg = u"Logged in user {0} ({1}) with password {2} and user_id {3}".format(
diff --git a/lms/lib/comment_client/user.py b/lms/lib/comment_client/user.py
index 014fe0a810ea38014a2dbca029c2e96b7b64d2a5..77e8b0d01169b606011b8788cc15f9869cfd6d93 100644
--- a/lms/lib/comment_client/user.py
+++ b/lms/lib/comment_client/user.py
@@ -80,7 +80,16 @@ class User(models.Model):
         retrieve_params = self.default_retrieve_params
         if self.attributes.get('course_id'):
             retrieve_params['course_id'] = self.course_id
-        response = perform_request('get', url, retrieve_params)
+        try:
+            response = perform_request('get', url, retrieve_params)
+        except CommentClientRequestError as e:
+            if e.status_code == 404:
+                # attempt to gracefully recover from a previous failure
+                # to sync this user to the comments service.
+                self.save()
+                response = perform_request('get', url, retrieve_params)
+            else:
+                raise
         self.update_attributes(**response)