diff --git a/reviewboard/scmtools/svn/__init__.py b/reviewboard/scmtools/svn/__init__.py
index eeae99b923f70f037dea6a275a8eaf2985bc0434..be9f6fa48d69d8aded61825f8b821ef4515caa15 100644
--- a/reviewboard/scmtools/svn/__init__.py
+++ b/reviewboard/scmtools/svn/__init__.py
@@ -6,6 +6,7 @@ import os
 import re
 import weakref
 
+from django.conf import settings
 from django.utils import six
 from django.utils.translation import ugettext as _
 
@@ -16,11 +17,12 @@ from reviewboard.scmtools.errors import (AuthenticationError,
                                          RepositoryNotFoundError,
                                          SCMError,
                                          UnverifiedCertificateError)
-from reviewboard.scmtools.svn.pysvn import Client, has_svn_backend
 from reviewboard.ssh import utils as sshutils
 
-if not has_svn_backend:  # not installed/couldn't be imported
-    from reviewboard.scmtools.svn.subvertpy import Client, has_svn_backend
+
+# These will be set later in recompute_svn_backend().
+Client = None
+has_svn_backend = False
 
 
 # Register these URI schemes so we can handle them properly.
@@ -46,7 +48,8 @@ class SVNTool(SCMTool):
     supports_authentication = True
     supports_post_commit = True
     dependencies = {
-        'modules': [Client.required_module],
+        'modules': [],  # This will get filled in later in
+                        # recompute_svn_backend()
     }
 
     def __init__(self, repository):
@@ -405,3 +408,47 @@ class SVNDiffParser(DiffParser):
             linenum += 3
 
         return linenum
+
+
+def recompute_svn_backend():
+    """Recomputes the SVNTool client backend to use.
+
+    Normally, this is only called once, but it may be used to reset the
+    backend for use in testing.
+    """
+    global Client
+    global has_svn_backend
+
+    Client = None
+    has_svn_backend = False
+    required_module = None
+
+    for backend_path in settings.SVNTOOL_BACKENDS:
+        try:
+            mod = __import__(six.binary_type(backend_path),
+                             fromlist=['Client', 'has_svn_backend'])
+
+            # Check that this is a valid SVN backend.
+            if (not hasattr(mod, 'has_svn_backend') or
+                not hasattr(mod, 'Client')):
+                logging.error('Attempted to load invalid SVN backend %s',
+                              backend_path)
+                continue
+
+            has_svn_backend = mod.has_svn_backend
+
+            # We want either the winning SVN backend or the first one to show
+            # up in the required module dependencies list.
+            if has_svn_backend or not required_module:
+                SVNTool.dependencies['modules'] = [mod.Client.required_module]
+
+            if has_svn_backend:
+                # We found a suitable backend.
+                logging.debug('Using %s backend for SVN', backend_path)
+                Client = mod.Client
+                break
+        except ImportError:
+            logging.error('Unable to load SVN backend %s',
+                          backend_path, exc_info=1)
+
+recompute_svn_backend()
diff --git a/reviewboard/settings.py b/reviewboard/settings.py
index bb11f43fe424903a0f174456b85f069ccce6ec4e..0f0f8568dea599c060003e99bdb91afbaccd5073 100644
--- a/reviewboard/settings.py
+++ b/reviewboard/settings.py
@@ -246,6 +246,15 @@ HOSTINGSVCS_HOOK_REGEX = (r'(?:Reviewed at %(server_url)sr/|Review request #)'
 HOSTINGSVCS_HOOK_REGEX_FLAGS = re.IGNORECASE
 
 
+# The SVN backends to attempt to load, in order. This is useful if more than
+# one type of backend is installed on a server, and you need to force usage
+# of a specific one.
+SVNTOOL_BACKENDS = [
+    'reviewboard.scmtools.svn.pysvn',
+    'reviewboard.scmtools.svn.subvertpy',
+]
+
+
 # Load local settings.  This can override anything in here, but at the very
 # least it needs to define database connectivity.
 try:
