diff --git a/reviewboard/hostingsvcs/assembla.py b/reviewboard/hostingsvcs/assembla.py
index db25427b3f09516586377f28ebeae43a4592dd89..35e86a6469d029031d62999b205c30c8a738db72 100644
--- a/reviewboard/hostingsvcs/assembla.py
+++ b/reviewboard/hostingsvcs/assembla.py
@@ -2,8 +2,8 @@
 from django.utils.translation import gettext_lazy as _
 
 from reviewboard.admin.server import get_hostname
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                                encrypt_password)
 
@@ -42,7 +42,7 @@
             })
 
 
-class Assembla(HostingService):
+class Assembla(BaseHostingService):
     """Hosting service support for Assembla.com.
 
     Assembla is a hosting service that offers, amongst other features,
diff --git a/reviewboard/hostingsvcs/base/__init__.py b/reviewboard/hostingsvcs/base/__init__.py
index d2c7b578b764a506e044d7fbf3529dd5ee1e78db..39004625831b71803b2cd3f2a98027471979cba5 100644
--- a/reviewboard/hostingsvcs/base/__init__.py
+++ b/reviewboard/hostingsvcs/base/__init__.py
@@ -27,8 +27,8 @@
     'HostingServiceClient',
     'HostingServiceHTTPRequest',
     'HostingServiceHTTPResponse',
+    'RemoteRepository',
     'hosting_service_registry',
-    'RemoteRepository',
 ]
 
 __autodoc_excludes__ = __all__
diff --git a/reviewboard/hostingsvcs/beanstalk.py b/reviewboard/hostingsvcs/beanstalk.py
index fd551a962d504b6aa32bc43b41460005ed066925..3b5cc81484d51d7fd5d97c334bb588ea4c4f233b 100644
--- a/reviewboard/hostingsvcs/beanstalk.py
+++ b/reviewboard/hostingsvcs/beanstalk.py
@@ -12,11 +12,11 @@
 from django.views.decorators.http import require_POST
 
 from reviewboard.admin.server import get_server_url
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.forms import (HostingServiceAuthForm,
                                            HostingServiceForm)
 from reviewboard.hostingsvcs.hook_utils import (close_all_review_requests,
                                                 get_review_request_id)
-from reviewboard.hostingsvcs.service import HostingService
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                                encrypt_password)
 from reviewboard.scmtools.errors import FileNotFoundError
@@ -214,7 +214,7 @@
                                   repository_id, hosting_service_id)
 
 
-class Beanstalk(HostingService):
+class Beanstalk(BaseHostingService):
     """Hosting service support for Beanstalk.
 
     Beanstalk is a source hosting service that supports Git and Subversion
diff --git a/reviewboard/hostingsvcs/bitbucket.py b/reviewboard/hostingsvcs/bitbucket.py
index 93ffd268110a3e95d0cab732e18f4c4988b47c46..ec74a278610cc8eaf66f70d70d2a7cc3e03ac9fb 100644
--- a/reviewboard/hostingsvcs/bitbucket.py
+++ b/reviewboard/hostingsvcs/bitbucket.py
@@ -15,6 +15,8 @@
 from django.views.decorators.http import require_POST
 
 from reviewboard.admin.server import build_server_url, get_server_url
+from reviewboard.hostingsvcs.base.client import HostingServiceClient
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             HostingServiceAPIError,
                                             HostingServiceError,
@@ -25,8 +27,6 @@
 from reviewboard.hostingsvcs.hook_utils import (close_all_review_requests,
                                                 get_repository_for_hook,
                                                 get_review_request_id)
-from reviewboard.hostingsvcs.service import (HostingService,
-                                             HostingServiceClient)
 from reviewboard.hostingsvcs.utils.paginator import APIPaginator
 from reviewboard.scmtools.core import Branch, Commit
 from reviewboard.scmtools.crypto_utils import encrypt_password
@@ -822,7 +822,7 @@
                    quote(path)))
 
 
-class Bitbucket(HostingService):
+class Bitbucket(BaseHostingService):
     """Hosting service support for Bitbucket.
 
     Bitbucket is a hosting service that supports Git and Mercurial
diff --git a/reviewboard/hostingsvcs/bugzilla.py b/reviewboard/hostingsvcs/bugzilla.py
index 34112daad3d4f6f185679e10a1521c0c0fa07775..938a78fb003ad23ba2ddc5886778942fe9dd2a2b 100644
--- a/reviewboard/hostingsvcs/bugzilla.py
+++ b/reviewboard/hostingsvcs/bugzilla.py
@@ -3,9 +3,9 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.bugtracker import BugTracker
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
 from reviewboard.admin.validation import validate_bug_tracker_base_hosting_url
 
 
@@ -24,7 +24,7 @@
         return self.cleaned_data['bugzilla_url'].rstrip('/')
 
 
-class Bugzilla(HostingService, BugTracker):
+class Bugzilla(BaseHostingService, BugTracker):
     name = 'Bugzilla'
     hosting_service_id = 'bugzilla'
     form = BugzillaForm
diff --git a/reviewboard/hostingsvcs/codebasehq.py b/reviewboard/hostingsvcs/codebasehq.py
index 37bcde3e2c5d54cff2f01f37468e217ddedbcbf0..c4f8a8240062835231ad6c1cecddd691a99307a4 100644
--- a/reviewboard/hostingsvcs/codebasehq.py
+++ b/reviewboard/hostingsvcs/codebasehq.py
@@ -5,13 +5,13 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _, gettext
 
+from reviewboard.hostingsvcs.base.client import HostingServiceClient
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             HostingServiceAPIError,
                                             RepositoryError)
 from reviewboard.hostingsvcs.forms import (HostingServiceAuthForm,
                                            HostingServiceForm)
-from reviewboard.hostingsvcs.service import (HostingService,
-                                             HostingServiceClient)
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                                encrypt_password)
 from reviewboard.scmtools.errors import FileNotFoundError
@@ -321,7 +321,7 @@
         return result
 
 
-class CodebaseHQ(HostingService):
+class CodebaseHQ(BaseHostingService):
     """Repository hosting support for Codebase.
 
     Codebase is a repository hosting service that supports Subversion, Git,
diff --git a/reviewboard/hostingsvcs/fake.py b/reviewboard/hostingsvcs/fake.py
index 6010b2b8d5e86e636e0e8d5b407ae12d78696dbf..10c27a0330e7f213116259e468e5d2a5011cc23e 100644
--- a/reviewboard/hostingsvcs/fake.py
+++ b/reviewboard/hostingsvcs/fake.py
@@ -1,7 +1,7 @@
-from reviewboard.hostingsvcs.service import HostingService
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 
 
-class FakeHostingService(HostingService):
+class FakeHostingService(BaseHostingService):
     """A hosting service that is not provided by Review Board.
 
     Fake hosting services are intended to be used to advertise for Beanbag,
diff --git a/reviewboard/hostingsvcs/fedorahosted.py b/reviewboard/hostingsvcs/fedorahosted.py
index 3b5bf4b2c13148572d00d72b00351f0837360225..ea6cf01951317f9f628799073b134a37c75c6d5e 100644
--- a/reviewboard/hostingsvcs/fedorahosted.py
+++ b/reviewboard/hostingsvcs/fedorahosted.py
@@ -2,7 +2,7 @@
 from django.utils.translation import gettext_lazy as _
 
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 
 
 class FedoraHostedForm(HostingServiceForm):
@@ -13,7 +13,7 @@
         widget=forms.TextInput(attrs={'size': '60'}))
 
 
-class FedoraHosted(HostingService):
+class FedoraHosted(BaseHostingService):
     """Hosting service support for fedorahosted.org.
 
     This was a hosting service for Git, Mercurial, and Subversion provided
diff --git a/reviewboard/hostingsvcs/fogbugz.py b/reviewboard/hostingsvcs/fogbugz.py
index 324af60adebc094630845c1ea4a8363219b8ab05..9b54904cb6cdf4326cf318c0fd61b1889a36f283 100644
--- a/reviewboard/hostingsvcs/fogbugz.py
+++ b/reviewboard/hostingsvcs/fogbugz.py
@@ -1,8 +1,8 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
 
 
 class FogBugzForm(HostingServiceForm):
@@ -15,7 +15,7 @@
         widget=forms.TextInput(attrs={'size': '60'}))
 
 
-class FogBugz(HostingService):
+class FogBugz(BaseHostingService):
     """Bug tracker support for FogBugz.
 
     FogBugz is a bug tracker service provided by Fog Creek. This integration
diff --git a/reviewboard/hostingsvcs/gerrit.py b/reviewboard/hostingsvcs/gerrit.py
index aa3ecb41e4be2f4b02b6eee01d80c99a16c57aaa..47f9f5e87c059efd0473d6794d7221d26725c688 100644
--- a/reviewboard/hostingsvcs/gerrit.py
+++ b/reviewboard/hostingsvcs/gerrit.py
@@ -10,15 +10,15 @@
 from django.utils.translation import gettext, gettext_lazy as _
 from djblets.util.decorators import cached_property
 
+from reviewboard.hostingsvcs.base.client import HostingServiceClient
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
+from reviewboard.hostingsvcs.base.http import HostingServiceHTTPResponse
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             HostingServiceError,
                                             RepositoryError,
                                             HostingServiceAPIError)
 from reviewboard.hostingsvcs.forms import (HostingServiceAuthForm,
                                            HostingServiceForm)
-from reviewboard.hostingsvcs.service import (HostingService,
-                                             HostingServiceClient,
-                                             HostingServiceHTTPResponse)
 from reviewboard.scmtools.core import Branch, Commit
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                                encrypt_password)
@@ -220,7 +220,7 @@
         """Process an HTTP error, converting to a HostingServiceError.
 
         Args:
-            request (reviewboard.hostingsvcs.service.
+            request (reviewboard.hostingsvcs.base.http.
                      HostingServiceHTTPRequest):
                 The request that resulted in an error.
 
@@ -252,7 +252,7 @@
             raise HostingServiceError(e.reason)
 
 
-class Gerrit(HostingService):
+class Gerrit(BaseHostingService):
     """Source code hosting support for Gerrit.
 
     Gerrit does not have an API that supports being a hosting service, so the
diff --git a/reviewboard/hostingsvcs/github.py b/reviewboard/hostingsvcs/github.py
index 5ab1ae6045ef4a4e898842bc72feee7460f9d999..93a574397d05612e155c899ebe4e9a9661fec4d1 100644
--- a/reviewboard/hostingsvcs/github.py
+++ b/reviewboard/hostingsvcs/github.py
@@ -21,6 +21,8 @@
 from django.views.decorators.http import require_POST
 
 from reviewboard.admin.server import build_server_url, get_server_url
+from reviewboard.hostingsvcs.base.client import HostingServiceClient
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.bugtracker import BugTracker
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             HostingServiceError,
@@ -33,8 +35,6 @@
                                                 get_repository_for_hook,
                                                 get_review_request_id)
 from reviewboard.hostingsvcs.repository import RemoteRepository
-from reviewboard.hostingsvcs.service import (HostingService,
-                                             HostingServiceClient)
 from reviewboard.hostingsvcs.utils.paginator import (APIPaginator,
                                                      ProxyPaginator)
 from reviewboard.scmtools.core import Branch, Commit
@@ -253,12 +253,12 @@
         """Process an HTTP response and return a result.
 
         Args:
-            response (reviewboard.hostingsvcs.service.
+            response (reviewboard.hostingsvcs.base.http.
                       HostingServiceHTTPResponse):
                 The response to process.
 
         Returns:
-            reviewboard.hostingsvcs.service.HostingServiceHTTPResponse:
+            reviewboard.hostingsvcs.base.http.HostingServiceHTTPResponse:
             The resulting response.
         """
         rate_limit_remaining = response.get_header('X-RateLimit-Remaining')
@@ -285,7 +285,7 @@
         and GitHub error payloads.
 
         Args:
-            request (reviewboard.hostingsvcs.service.
+            request (reviewboard.hostingsvcs.base.http.
                      HostingServiceHTTPRequest):
                 The request that resulted in an error.
 
@@ -603,7 +603,7 @@
         return review_request_id_to_commits_map
 
 
-class GitHub(HostingService, BugTracker):
+class GitHub(BaseHostingService, BugTracker):
     name = _('GitHub')
     hosting_service_id = 'github'
     plans = [
diff --git a/reviewboard/hostingsvcs/gitlab.py b/reviewboard/hostingsvcs/gitlab.py
index 969da013d29aec61b99344de903e8bfa8dcf8629..dd4261b50ece115b64d2766f18f503213391eb23 100644
--- a/reviewboard/hostingsvcs/gitlab.py
+++ b/reviewboard/hostingsvcs/gitlab.py
@@ -12,13 +12,13 @@
 from djblets.cache.backend import cache_memoize
 
 from reviewboard.admin.support import get_kb_url
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             HostingServiceError,
                                             InvalidPlanError,
                                             RepositoryError)
 from reviewboard.hostingsvcs.forms import (HostingServiceAuthForm,
                                            HostingServiceForm)
-from reviewboard.hostingsvcs.service import HostingService
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                                encrypt_password)
 from reviewboard.scmtools.errors import FileNotFoundError
@@ -234,7 +234,7 @@
         widget=forms.TextInput(attrs={'size': '60'}))
 
 
-class GitLab(HostingService):
+class GitLab(BaseHostingService):
     """Hosting service support for GitLab.
 
     GitLab is a self-installed source hosting service that supports Git
diff --git a/reviewboard/hostingsvcs/gitorious.py b/reviewboard/hostingsvcs/gitorious.py
index 399579e3338096923e8aad91e5e6ff875a794b8a..68fb7c2ef0dd9f9cd32f9c2f748aea8bfce4b4d9 100644
--- a/reviewboard/hostingsvcs/gitorious.py
+++ b/reviewboard/hostingsvcs/gitorious.py
@@ -1,8 +1,8 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
 
 
 class GitoriousForm(HostingServiceForm):
@@ -19,7 +19,7 @@
         widget=forms.TextInput(attrs={'size': '60'}))
 
 
-class Gitorious(HostingService):
+class Gitorious(BaseHostingService):
     name = 'Gitorious'
     hosting_service_id = 'gitorious'
     form = GitoriousForm
diff --git a/reviewboard/hostingsvcs/googlecode.py b/reviewboard/hostingsvcs/googlecode.py
index 57db927193b7bf8904b41ab5de3c5cc4706770d0..74921067c6b4524f1d0b72185517ebb50dd51566 100644
--- a/reviewboard/hostingsvcs/googlecode.py
+++ b/reviewboard/hostingsvcs/googlecode.py
@@ -1,8 +1,8 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
 
 
 class GoogleCodeForm(HostingServiceForm):
@@ -13,7 +13,7 @@
         widget=forms.TextInput(attrs={'size': '60'}))
 
 
-class GoogleCode(HostingService):
+class GoogleCode(BaseHostingService):
     """Hosting service support for Google Code.
 
     This was a hosting service for Mercurial and Subversion provided by
diff --git a/reviewboard/hostingsvcs/jira.py b/reviewboard/hostingsvcs/jira.py
index 6e9f8ba7664899e3ab3fcc9288176c66ed944387..fb3c369db2a29e15798e65107dce87d4ed9dca55 100644
--- a/reviewboard/hostingsvcs/jira.py
+++ b/reviewboard/hostingsvcs/jira.py
@@ -10,9 +10,9 @@
     has_jira = False
 
 from reviewboard.admin.validation import validate_bug_tracker_base_hosting_url
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.bugtracker import BugTracker
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
 
 
 logger = logging.getLogger(__name__)
@@ -30,7 +30,7 @@
         return self.cleaned_data['jira_url'].rstrip('/ ')
 
 
-class JIRA(HostingService, BugTracker):
+class JIRA(BaseHostingService, BugTracker):
     name = 'JIRA'
     hosting_service_id = 'jira'
     form = JIRAForm
diff --git a/reviewboard/hostingsvcs/kiln.py b/reviewboard/hostingsvcs/kiln.py
index 7ca8e64afca20a430163bebd0688d21641732027..734da0eef02c6bab6a5aa65c1870024568df6716 100644
--- a/reviewboard/hostingsvcs/kiln.py
+++ b/reviewboard/hostingsvcs/kiln.py
@@ -5,12 +5,12 @@
 from django import forms
 from django.utils.translation import gettext, gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.client import HostingServiceClient
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             HostingServiceError,
                                             RepositoryError)
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import (HostingService,
-                                             HostingServiceClient)
 from reviewboard.scmtools.errors import FileNotFoundError
 
 
@@ -179,7 +179,7 @@
             raise KilnAPIError(rsp['errors'])
 
 
-class Kiln(HostingService):
+class Kiln(BaseHostingService):
     """Hosting service support for Kiln On Demand.
 
     Kiln On Demand supports Git and Mercurial repositories, accessible
diff --git a/reviewboard/hostingsvcs/rbgateway.py b/reviewboard/hostingsvcs/rbgateway.py
index 633be7d2edaf9f5247eb11ecf936c51e0ca80f1a..cbd1656ed8279d0f54d15d724e1d20a2a2357560 100644
--- a/reviewboard/hostingsvcs/rbgateway.py
+++ b/reviewboard/hostingsvcs/rbgateway.py
@@ -13,6 +13,8 @@
 from django.utils.translation import gettext_lazy as _, gettext
 
 from reviewboard.admin.server import build_server_url, get_server_url
+from reviewboard.hostingsvcs.base.client import HostingServiceClient
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             HostingServiceAPIError,
                                             HostingServiceError)
@@ -20,8 +22,6 @@
 from reviewboard.hostingsvcs.hook_utils import (close_all_review_requests,
                                                 get_repository_for_hook,
                                                 get_review_request_id)
-from reviewboard.hostingsvcs.service import (HostingService,
-                                             HostingServiceClient)
 from reviewboard.scmtools.core import Branch, Commit, UNKNOWN
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                                encrypt_password)
@@ -451,8 +451,8 @@
         in its place.
 
         Args:
-            request (reviewboard.hostingsvcs.service.HostingServiceHTTPRequest,
-                     unused):
+            request (reviewboard.hostingsvcs.base.http.
+                     HostingServiceHTTPRequest, unused):
                 The request that resulted in an error.
 
             e (urllib2.URLError):
@@ -599,7 +599,7 @@
                        quote(path)))
 
 
-class ReviewBoardGateway(HostingService):
+class ReviewBoardGateway(BaseHostingService):
     """Hosting service support for Review Board Gateway.
 
     Review Board Gateway is a lightweight self-installed source hosting service
diff --git a/reviewboard/hostingsvcs/redmine.py b/reviewboard/hostingsvcs/redmine.py
index 7432ef53c85c74ad16661e49a623398d9812fc7e..dcce1a26d400ecb49bae7c75ce28f0d6eca5c34d 100644
--- a/reviewboard/hostingsvcs/redmine.py
+++ b/reviewboard/hostingsvcs/redmine.py
@@ -1,9 +1,9 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.admin.validation import validate_bug_tracker_base_hosting_url
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
-from reviewboard.admin.validation import validate_bug_tracker_base_hosting_url
 
 
 class RedmineForm(HostingServiceForm):
@@ -15,7 +15,7 @@
         validators=[validate_bug_tracker_base_hosting_url])
 
 
-class Redmine(HostingService):
+class Redmine(BaseHostingService):
     name = 'Redmine'
     hosting_service_id = 'redmine'
     form = RedmineForm
diff --git a/reviewboard/hostingsvcs/service.py b/reviewboard/hostingsvcs/service.py
index 00b774a9ff78ccf8c3cb04ae8950fc88904edc3c..13dc1436061fcaabe207aefc9f4f78ecbee659be 100644
--- a/reviewboard/hostingsvcs/service.py
+++ b/reviewboard/hostingsvcs/service.py
@@ -18,21 +18,72 @@
 from __future__ import annotations
 
 import logging
-from typing import List, Optional, Type
-
-from reviewboard.hostingsvcs.base import (
-    BaseHostingService as HostingService,
-    HostingServiceClient,
-    HostingServiceHTTPRequest,
-    HostingServiceHTTPResponse,
-    hosting_service_registry)
+
+from housekeeping import ClassMovedMixin, func_moved
+
+from reviewboard.deprecation import RemovedInReviewBoard100Warning
+from reviewboard.hostingsvcs.base import client, http
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
+from reviewboard.hostingsvcs.base.registry import hosting_service_registry
 from reviewboard.hostingsvcs.base.registry import HostingServiceRegistry
 
 
 logger = logging.getLogger(__name__)
 
 
-def get_hosting_services() -> List[Type[HostingService]]:
+class HostingService(ClassMovedMixin,
+                     BaseHostingService,
+                     warning_cls=RemovedInReviewBoard100Warning):
+    """An interface to a hosting service for repositories and bug trackers.
+
+    Deprecated:
+        8.0:
+        This has been moved to :py:class:`reviewboard.hostingsvcs.base.
+        hosting_service.BaseHostingService`. The legacy import will be removed
+        in Review Board 10.
+    """
+
+
+class HostingServiceClient(ClassMovedMixin,
+                           client.HostingServiceClient,
+                           warning_cls=RemovedInReviewBoard100Warning):
+    """Client for communicating with a hosting service's API.
+
+    Deprecated:
+        8.0:
+        This has been moved to :py:class:`reviewboard.hostingsvcs.base.client.
+        HostingServiceClient`. The legacy import will be removed in Review
+        Board 10.
+    """
+
+
+class HostingServiceHTTPRequest(ClassMovedMixin,
+                                http.HostingServiceHTTPRequest,
+                                warning_cls=RemovedInReviewBoard100Warning):
+    """A request that can use any HTTP method.
+
+    Deprecated:
+        8.0:
+        This has been moved to :py:class:`reviewboard.hostingsvcs.base.http.
+        HostingServiceHTTPRequest`. The legacy import will be removed in Review
+        Board 10.
+    """
+
+
+class HostingServiceHTTPResponse(ClassMovedMixin,
+                                 http.HostingServiceHTTPResponse,
+                                 warning_cls=RemovedInReviewBoard100Warning):
+    """An HTTP response from the server.
+
+    Deprecated:
+        8.0:
+        This has been moved to :py:class:`reviewboard.hostingsvcs.base.http.
+        HostingServiceHTTPRequest`. The legacy import will be removed in Review
+        Board 10.
+    """
+
+
+def get_hosting_services() -> list[type[BaseHostingService]]:
     """Return the list of hosting services.
 
     Returns:
@@ -43,9 +94,11 @@
     return list(hosting_service_registry)
 
 
+@func_moved(RemovedInReviewBoard100Warning,
+            new_func=hosting_service_registry.get_hosting_service)
 def get_hosting_service(
     name: str,
-) -> Optional[Type[HostingService]]:
+) -> type[BaseHostingService] | None:
     """Return the hosting service with the given name.
 
     If the hosting service is not found, None will be returned.
@@ -61,9 +114,11 @@
     return hosting_service_registry.get_hosting_service(name)
 
 
+@func_moved(RemovedInReviewBoard100Warning,
+            new_func=hosting_service_registry.register)
 def register_hosting_service(
     name: str,
-    cls: Type[HostingService],
+    cls: type[BaseHostingService],
 ) -> None:
     """Register a custom hosting service class.
 
@@ -90,6 +145,8 @@
     hosting_service_registry.register(cls)
 
 
+@func_moved(RemovedInReviewBoard100Warning,
+            new_func=hosting_service_registry.unregister_by_id)
 def unregister_hosting_service(
     name: str,
 ) -> None:
diff --git a/reviewboard/hostingsvcs/sourceforge.py b/reviewboard/hostingsvcs/sourceforge.py
index d46c3a5c67af8bec399c7f6f6d412b6642adbb39..1aa60f9adef292517cb2bee9fc860a3efec2042d 100644
--- a/reviewboard/hostingsvcs/sourceforge.py
+++ b/reviewboard/hostingsvcs/sourceforge.py
@@ -1,8 +1,8 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
 
 
 class SourceForgeForm(HostingServiceForm):
@@ -13,7 +13,7 @@
         widget=forms.TextInput(attrs={'size': '60'}))
 
 
-class SourceForge(HostingService):
+class SourceForge(BaseHostingService):
     name = 'SourceForge'
     hosting_service_id = 'sourceforge'
     form = SourceForgeForm
diff --git a/reviewboard/hostingsvcs/splat.py b/reviewboard/hostingsvcs/splat.py
index 1d3869d12b789fe049f3bf3f99daf95d492bdf60..05836109e84852de567729a8f72756a474b0621f 100644
--- a/reviewboard/hostingsvcs/splat.py
+++ b/reviewboard/hostingsvcs/splat.py
@@ -5,9 +5,9 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.bugtracker import BugTracker
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
 
 
 logger = logging.getLogger(__name__)
@@ -23,7 +23,7 @@
         widget=forms.TextInput(attrs={'size': 60}))
 
 
-class Splat(HostingService, BugTracker):
+class Splat(BaseHostingService, BugTracker):
     """The Splat bug tracker.
 
     Splat is a SaaS bugtracker hosted at https://hellosplat.com. It is owned
diff --git a/reviewboard/hostingsvcs/tests/test_kiln.py b/reviewboard/hostingsvcs/tests/test_kiln.py
index f23023097738d1ac629833421a6bce14c2dfde05..f5f38a112227ef5c779198f5a54e474b5a95a24d 100644
--- a/reviewboard/hostingsvcs/tests/test_kiln.py
+++ b/reviewboard/hostingsvcs/tests/test_kiln.py
@@ -1,7 +1,7 @@
 """Unit tests for the Kiln hosting service."""
 
+from reviewboard.hostingsvcs.base.client import HostingServiceClient
 from reviewboard.hostingsvcs.errors import RepositoryError
-from reviewboard.hostingsvcs.service import HostingServiceClient
 from reviewboard.hostingsvcs.testing import HostingServiceTestCase
 
 
diff --git a/reviewboard/hostingsvcs/trac.py b/reviewboard/hostingsvcs/trac.py
index 093849367f231a2c61b620d385344db521111e32..8500bde92c0af266a416b46203f306c017573b0b 100644
--- a/reviewboard/hostingsvcs/trac.py
+++ b/reviewboard/hostingsvcs/trac.py
@@ -1,9 +1,9 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.admin.validation import validate_bug_tracker_base_hosting_url
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
-from reviewboard.admin.validation import validate_bug_tracker_base_hosting_url
 
 
 class TracForm(HostingServiceForm):
@@ -18,7 +18,7 @@
         return self.cleaned_data['trac_url'].rstrip('/')
 
 
-class Trac(HostingService):
+class Trac(BaseHostingService):
     name = 'Trac'
     hosting_service_id = 'trac'
     form = TracForm
diff --git a/reviewboard/hostingsvcs/unfuddle.py b/reviewboard/hostingsvcs/unfuddle.py
index f880593d85753ec55671db4e0e87418857f4d193..29fe855cc210510729ffd12fd7096937e284b171 100644
--- a/reviewboard/hostingsvcs/unfuddle.py
+++ b/reviewboard/hostingsvcs/unfuddle.py
@@ -4,10 +4,10 @@
 from django import forms
 from django.utils.translation import gettext, gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             RepositoryError)
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                                encrypt_password)
 from reviewboard.scmtools.errors import FileNotFoundError
@@ -40,7 +40,7 @@
         widget=forms.TextInput(attrs={'size': '60'}))
 
 
-class Unfuddle(HostingService):
+class Unfuddle(BaseHostingService):
     """Hosting service support for Unfuddle.
 
     Unfuddle is a source hosting service that supports Git and Subversion
diff --git a/reviewboard/hostingsvcs/versionone.py b/reviewboard/hostingsvcs/versionone.py
index dae4daec713c3127f36f39938aa7aa05d66f28a8..c1a0b92bd5bd7f6dd1d91bdd16a1b0c9044e7c4b 100644
--- a/reviewboard/hostingsvcs/versionone.py
+++ b/reviewboard/hostingsvcs/versionone.py
@@ -2,8 +2,8 @@
 from django.utils.translation import gettext_lazy as _
 
 from reviewboard.admin.validation import validate_bug_tracker_base_hosting_url
+from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.forms import HostingServiceForm
-from reviewboard.hostingsvcs.service import HostingService
 
 
 class VersionOneForm(HostingServiceForm):
@@ -15,7 +15,7 @@
         validators=[validate_bug_tracker_base_hosting_url])
 
 
-class VersionOne(HostingService):
+class VersionOne(BaseHostingService):
     name = 'VersionOne'
     hosting_service_id = 'versionone'
     form = VersionOneForm
diff --git a/reviewboard/scmtools/admin.py b/reviewboard/scmtools/admin.py
index 3a9addfdcdf4837c405be12239c101807b9d7c49..89dc2b4112d85d93ad459dd9461956462eaef522 100644
--- a/reviewboard/scmtools/admin.py
+++ b/reviewboard/scmtools/admin.py
@@ -22,7 +22,8 @@
 
 if TYPE_CHECKING:
     from django.utils.safestring import SafeString
-    from reviewboard.hostingsvcs.service import HostingService
+
+    from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
     from reviewboard.scmtools.core import SCMTool
 
 
@@ -118,7 +119,7 @@
         hosting_account = repository.hosting_account
 
         if hosting_account:
-            service: Optional[HostingService]
+            service: BaseHostingService | None
 
             try:
                 service = hosting_account.service
@@ -170,7 +171,7 @@
                                css_class, url, name)
 
         if repository.hosting_account:
-            service: Optional[HostingService]
+            service: BaseHostingService | None
 
             try:
                 service = repository.hosting_account.service
diff --git a/reviewboard/scmtools/forms.py b/reviewboard/scmtools/forms.py
index d79256603542b65acad5a28b11617907047a481c..04e3bde475aaff0c0de2d19682d0a85cba80edb0 100644
--- a/reviewboard/scmtools/forms.py
+++ b/reviewboard/scmtools/forms.py
@@ -51,7 +51,7 @@
                                     UnknownHostKeyError)
 
 if TYPE_CHECKING:
-    from reviewboard.hostingsvcs.service import HostingService
+    from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 
 
 logger = logging.getLogger(__name__)
@@ -852,7 +852,7 @@
         # fields here that aren't dependent on any loaded hosting service or
         # SCMTool forms or state.
         instance = self.instance
-        cur_hosting_service_cls: Optional[Type[HostingService]] = None
+        cur_hosting_service_cls: (type[BaseHostingService] | None) = None
 
         if instance:
             cur_scmtool_cls = instance.scmtool_class
@@ -1427,7 +1427,7 @@
         hosting_account = self.instance.hosting_account
 
         if hosting_account:
-            hosting_service: Optional[HostingService]
+            hosting_service: BaseHostingService | None
 
             try:
                 hosting_service = hosting_account.service
