diff --git a/conftest.py b/conftest.py
index 4917ed9df786dfbb8ed18d967a764720b38be3eb_Y29uZnRlc3QucHk=..5cca85c5e7f50ae133314d7dc69bf30a983f333e_Y29uZnRlc3QucHk= 100644
--- a/conftest.py
+++ b/conftest.py
@@ -12,5 +12,5 @@
 
 @pytest.fixture(scope='module')
 def grpc_server(_grpc_server, grpc_addr, server_repos_root):
-    repos_root_bytes = str(server_repos_root).encode()
+    storages = dict(default=str(server_repos_root / 'default').encode())
 
@@ -16,3 +16,3 @@
 
-    add_CommitServiceServicer_to_server(CommitServicer(repos_root_bytes),
+    add_CommitServiceServicer_to_server(CommitServicer(storages),
                                         _grpc_server)
@@ -18,4 +18,4 @@
                                         _grpc_server)
-    add_RefServiceServicer_to_server(RefServicer(repos_root_bytes),
+    add_RefServiceServicer_to_server(RefServicer(storages),
                                      _grpc_server)
     add_RepositoryServiceServicer_to_server(
@@ -20,6 +20,6 @@
                                      _grpc_server)
     add_RepositoryServiceServicer_to_server(
-        RepositoryServiceServicer(repos_root_bytes),
+        RepositoryServiceServicer(storages),
         _grpc_server)
     _grpc_server.add_insecure_port(grpc_addr)
     _grpc_server.start()
diff --git a/hgext3rd/hgitaly/__init__.py b/hgext3rd/hgitaly/__init__.py
index 4917ed9df786dfbb8ed18d967a764720b38be3eb_aGdleHQzcmQvaGdpdGFseS9fX2luaXRfXy5weQ==..5cca85c5e7f50ae133314d7dc69bf30a983f333e_aGdleHQzcmQvaGdpdGFseS9fX2luaXRfXy5weQ== 100644
--- a/hgext3rd/hgitaly/__init__.py
+++ b/hgext3rd/hgitaly/__init__.py
@@ -62,7 +62,7 @@
          norepo=True
          )
 def serve(ui, **opts):
-    """Start a HGitaly server.
+    """Start a HGitaly server with only one storage, named 'default'
 
     By default the root of repositories is read from the
     `heptapod.repositories-root` configuration item if present.
@@ -85,4 +85,6 @@
                 b"'heptapod.repositories-root'. Please define it or run "
                 b"the command with the --repositories-root option."
                 ))
+    storages = dict(default=repos_root)
+
     server = grpc.server(futures.ThreadPoolExecutor(max_workers=1))
@@ -88,4 +90,4 @@
     server = grpc.server(futures.ThreadPoolExecutor(max_workers=1))
-    add_CommitServiceServicer_to_server(CommitServicer(repos_root), server)
-    add_RefServiceServicer_to_server(RefServicer(repos_root), server)
+    add_CommitServiceServicer_to_server(CommitServicer(storages), server)
+    add_RefServiceServicer_to_server(RefServicer(storages), server)
     add_RepositoryServiceServicer_to_server(
@@ -91,5 +93,5 @@
     add_RepositoryServiceServicer_to_server(
-        RepositoryServiceServicer(repos_root), server)
+        RepositoryServiceServicer(storages), server)
 
     for url in listen_urls:
         try:
diff --git a/hgitaly/servicer.py b/hgitaly/servicer.py
index 4917ed9df786dfbb8ed18d967a764720b38be3eb_aGdpdGFseS9zZXJ2aWNlci5weQ==..5cca85c5e7f50ae133314d7dc69bf30a983f333e_aGdpdGFseS9zZXJ2aWNlci5weQ== 100644
--- a/hgitaly/servicer.py
+++ b/hgitaly/servicer.py
@@ -22,6 +22,7 @@
 
     Attributes:
 
-    - `repositories_root`: should be given as bytes, since we'll have
+    - :attr:`storages`: a :class:`dict` mapping storage names to corresponding
+      root directory absolute paths, which are given as bytes since we'll have
       to convert paths to bytes anyway, which is the only promise a filesystem
       can make, and what Mercurial expects.
@@ -26,4 +27,6 @@
       to convert paths to bytes anyway, which is the only promise a filesystem
       can make, and what Mercurial expects.
+    - :attr:`ui`: base :class:`mercurial.ui.ui` instance from which repository
+      uis are derived. In particular, it bears the common configuration.
     """
 
@@ -28,7 +31,7 @@
     """
 
-    def __init__(self, repositories_root):
-        self.repos_root = repositories_root
+    def __init__(self, storages):
+        self.storages = storages
         self.ui = uimod.ui.load()
 
     def load_repo(self, repository: Repository):
@@ -38,4 +41,10 @@
         rpath = repository.relative_path
         if rpath.endswith('.git'):
             rpath = rpath[:-4] + '.hg'
+
+        root_dir = self.storages.get(repository.storage_name)
+        if root_dir is None:
+            # TODO produce proper error. Keep uncovered by tests until then
+            raise KeyError("No storage named %r" % repository.storage_name)
+
         # GitLab filesystem paths are always ASCII
@@ -41,5 +50,5 @@
         # GitLab filesystem paths are always ASCII
-        repo_path = os.path.join(self.repos_root, rpath.encode('ascii'))
+        repo_path = os.path.join(root_dir, rpath.encode('ascii'))
         logger.info("loading repo at %r", repo_path)
 
         # ensure caller gets private copy of ui
diff --git a/hgitaly/tests/common.py b/hgitaly/tests/common.py
index 4917ed9df786dfbb8ed18d967a764720b38be3eb_aGdpdGFseS90ZXN0cy9jb21tb24ucHk=..5cca85c5e7f50ae133314d7dc69bf30a983f333e_aGdpdGFseS90ZXN0cy9jb21tb24ucHk= 100644
--- a/hgitaly/tests/common.py
+++ b/hgitaly/tests/common.py
@@ -9,9 +9,9 @@
 from ..stub.shared_pb2 import Repository
 
 
-def make_empty_repo(server_repos_root, relative_path='repo1'):
+def make_empty_repo(storages_root, relative_path='repo1', storage='default'):
     """Create an empty repo, ready for most of HGitaly tests.
 
     :relative_path: path to the repo, relative to server_repos_root, and
                     hence also relative path in the sense of Gitaly protocol.
                     Can be given as :class:`str` or :class:`pathlib.Path`
@@ -13,7 +13,10 @@
     """Create an empty repo, ready for most of HGitaly tests.
 
     :relative_path: path to the repo, relative to server_repos_root, and
                     hence also relative path in the sense of Gitaly protocol.
                     Can be given as :class:`str` or :class:`pathlib.Path`
+    :storage: name of the target storage, will have to be created and
+              registered before hand on the testing grpc server if needed.
+
     return: wrapper, gRPC Repository message
     """
@@ -18,6 +21,6 @@
     return: wrapper, gRPC Repository message
     """
-    repo_path = server_repos_root / relative_path
+    repo_path = storages_root / storage / relative_path
     wrapper = LocalRepoWrapper.init(repo_path,
                                     config={b'extensions': {b'topic': b''}}
                                     )
@@ -26,5 +29,6 @@
     (repo_path / '.hg' / 'hgrc').write_text(
         '\n'.join(('[extensions]', 'topic=')))
 
-    grpc_repo = Repository(relative_path=str(relative_path))
+    grpc_repo = Repository(relative_path=str(relative_path),
+                           storage_name=storage)
     return wrapper, grpc_repo