diff --git a/include/ircd/m/room/bootstrap.h b/include/ircd/m/room/bootstrap.h
index 9ff681aa9..de0337ca6 100644
--- a/include/ircd/m/room/bootstrap.h
+++ b/include/ircd/m/room/bootstrap.h
@@ -21,4 +21,6 @@ struct ircd::m::room::bootstrap
 
 	// synchronous make_join, eval; asynchronous send_join
 	bootstrap(event::id::buf &, const room::id &, const m::id::user &, const string_view &host);
+
+	static bool required(const id &);
 };
diff --git a/matrix/room_bootstrap.cc b/matrix/room_bootstrap.cc
index ac5d33f24..b6435e498 100644
--- a/matrix/room_bootstrap.cc
+++ b/matrix/room_bootstrap.cc
@@ -797,3 +797,24 @@ catch(const std::exception &e)
 	// bootstrap process.
 	throw;
 }
+
+bool
+ircd::m::room::bootstrap::required(const id &room_id)
+{
+	// No bootstrap for my rooms
+	//TODO: issue for clustering
+	if(my(room_id))
+		return false;
+
+	// We have nothing for the room
+	 if(!exists(room_id))
+		return true;
+
+	// No users are currently joined from this server;
+	//TODO: bootstrap shouldn't have to be used to re-sync a room where we have
+	//TODO: some partial state, so this condition should be eliminated.
+	if(local_joined(room_id) == 0)
+		return true;
+
+	return false;
+}
diff --git a/matrix/room_join.cc b/matrix/room_join.cc
index 820e45197..19af2ee71 100644
--- a/matrix/room_join.cc
+++ b/matrix/room_join.cc
@@ -8,11 +8,6 @@
 // copyright notice and this permission notice is present in all copies. The
 // full license for this software is available in the LICENSE file.
 
-namespace ircd::m
-{
-	static bool need_bootstrap(const room::id &);
-}
-
 ircd::m::event::id::buf
 ircd::m::join(const room::alias &room_alias,
               const user::id &user_id)
@@ -28,7 +23,7 @@ ircd::m::join(const room::alias &room_alias,
 		m::room_id(room_alias)
 	};
 
-	if(need_bootstrap(room_id))
+	if(room::bootstrap::required(room_id))
 	{
 		m::event::id::buf ret;
 		m::room::bootstrap
@@ -58,7 +53,7 @@ ircd::m::join(const m::room &room,
 		};
 
 	// Branch for when nothing is known about the room.
-	if(need_bootstrap(room))
+	if(room::bootstrap::required(room))
 	{
 		// The bootstrap condcts a blocking make_join and issues a join
 		// event, returning the event_id; afterward asynchronously it will
@@ -140,24 +135,3 @@ ircd::m::join(const m::room &room,
 
 	return commit(room, event, content);
 }
-
-bool
-ircd::m::need_bootstrap(const room::id &room_id)
-{
-	// No bootstrap for my rooms
-	//TODO: issue for clustering
-	if(my(room_id))
-		return false;
-
-	// We have nothing for the room
-	if(!exists(room_id))
-		return true;
-
-	// No users are currently joined from this server;
-	//TODO: bootstrap shouldn't have to be used to re-sync a room where we have
-	//TODO: some partial state, so this condition should be eliminated.
-	if(local_joined(room_id) == 0)
-		return true;
-
-	return false;
-}