diff --git a/Cargo.lock b/Cargo.lock
index 6ffd3473cc047167972824d6f6d980509cbfc202..28a4395e15aefb139f53cc65f0d2a16afcfe9846 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -157,7 +157,7 @@ dependencies = [
  "addr2line",
  "cfg-if",
  "libc",
- "miniz_oxide 0.4.1",
+ "miniz_oxide 0.4.2",
  "object",
  "rustc-demangle",
 ]
@@ -1054,11 +1054,12 @@ dependencies = [
 
 [[package]]
 name = "miniz_oxide"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d7559a8a40d0f97e1edea3220f698f78b1c5ab67532e49f68fde3910323b722"
+checksum = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9"
 dependencies = [
  "adler",
+ "autocfg",
 ]
 
 [[package]]
@@ -1634,7 +1635,7 @@ dependencies = [
 [[package]]
 name = "ruma"
 version = "0.0.1"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "ruma-api",
  "ruma-appservice-api",
@@ -1650,7 +1651,7 @@ dependencies = [
 [[package]]
 name = "ruma-api"
 version = "0.17.0-alpha.1"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "http",
  "percent-encoding",
@@ -1665,7 +1666,7 @@ dependencies = [
 [[package]]
 name = "ruma-api-macros"
 version = "0.17.0-alpha.1"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "proc-macro-crate",
  "proc-macro2",
@@ -1676,7 +1677,7 @@ dependencies = [
 [[package]]
 name = "ruma-appservice-api"
 version = "0.2.0-alpha.1"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "ruma-api",
  "ruma-common",
@@ -1689,7 +1690,7 @@ dependencies = [
 [[package]]
 name = "ruma-client-api"
 version = "0.10.0-alpha.1"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "assign",
  "http",
@@ -1708,7 +1709,7 @@ dependencies = [
 [[package]]
 name = "ruma-common"
 version = "0.2.0"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "js_int",
  "ruma-api",
@@ -1722,7 +1723,7 @@ dependencies = [
 [[package]]
 name = "ruma-events"
 version = "0.22.0-alpha.1"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "js_int",
  "ruma-common",
@@ -1737,7 +1738,7 @@ dependencies = [
 [[package]]
 name = "ruma-events-macros"
 version = "0.22.0-alpha.1"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "proc-macro-crate",
  "proc-macro2",
@@ -1748,7 +1749,7 @@ dependencies = [
 [[package]]
 name = "ruma-federation-api"
 version = "0.0.3"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "js_int",
  "ruma-api",
@@ -1763,7 +1764,7 @@ dependencies = [
 [[package]]
 name = "ruma-identifiers"
 version = "0.17.4"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "rand",
  "ruma-identifiers-macros",
@@ -1775,7 +1776,7 @@ dependencies = [
 [[package]]
 name = "ruma-identifiers-macros"
 version = "0.17.4"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1786,7 +1787,7 @@ dependencies = [
 [[package]]
 name = "ruma-identifiers-validation"
 version = "0.1.1"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "serde",
  "strum",
@@ -1795,7 +1796,7 @@ dependencies = [
 [[package]]
 name = "ruma-serde"
 version = "0.2.3"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "form_urlencoded",
  "itoa",
@@ -1807,7 +1808,7 @@ dependencies = [
 [[package]]
 name = "ruma-signatures"
 version = "0.6.0-dev.1"
-source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#8d763abaecb13f4799a31ecf1e0da77d2bc956a6"
+source = "git+https://github.com/timokoesters/ruma?branch=timo-fed-fixes#ee66e30cbd58aecbbfde1d7008d7d6457deef87b"
 dependencies = [
  "base64",
  "ring",
diff --git a/src/client_server/alias.rs b/src/client_server/alias.rs
index bfdaecac455f5eedf1d7a09ac9c1fe6158549515..0ec43f576c1900fe4a6f07f6cedf95cebda566d9 100644
--- a/src/client_server/alias.rs
+++ b/src/client_server/alias.rs
@@ -63,7 +63,7 @@ pub async fn get_alias_helper(
     if room_alias.server_name() != db.globals.server_name() {
         let response = server_server::send_request(
             &db,
-            room_alias.server_name().to_string(),
+            room_alias.server_name(),
             federation::query::get_room_information::v1::Request { room_alias },
         )
         .await?;
@@ -79,5 +79,5 @@ pub async fn get_alias_helper(
             "Room with alias not found.",
         ))?;
 
-    Ok(get_alias::Response::new(room_id, vec![db.globals.server_name().to_string()]).into())
+    Ok(get_alias::Response::new(room_id, vec![db.globals.server_name().to_owned()]).into())
 }
diff --git a/src/client_server/directory.rs b/src/client_server/directory.rs
index 2764d2c5252e4fa96d6ae187e6e54c7b6d28de18..a68d8dd134e7a4d341a1f3d6998d99300965f79d 100644
--- a/src/client_server/directory.rs
+++ b/src/client_server/directory.rs
@@ -19,7 +19,7 @@
         room::{avatar, canonical_alias, guest_access, history_visibility, name, topic},
         EventType,
     },
-    Raw,
+    Raw, ServerName,
 };
 
 #[cfg(feature = "conduit_bin")]
@@ -65,9 +65,9 @@ pub async fn get_public_rooms_route(
 ) -> ConduitResult<get_public_rooms::Response> {
     let response = get_public_rooms_filtered_helper(
         &db,
-        body.body.server.as_deref(),
-        body.body.limit,
-        body.body.since.as_deref(),
+        body.server.as_deref(),
+        body.limit,
+        body.since.as_deref(),
         None, // This is not used
         None, // This is not used
     )
@@ -119,7 +119,7 @@ pub async fn get_room_visibility_route(
 
 pub async fn get_public_rooms_filtered_helper(
     db: &Database,
-    server: Option<&str>,
+    server: Option<&ServerName>,
     limit: Option<js_int::UInt>,
     since: Option<&str>,
     _filter: Option<IncomingFilter>,
@@ -131,7 +131,7 @@ pub async fn get_public_rooms_filtered_helper(
     {
         let response = server_server::send_request(
             &db,
-            other_server.to_owned(),
+            other_server,
             federation::directory::get_public_rooms::v1::Request {
                 limit,
                 since: since.as_deref(),
diff --git a/src/client_server/membership.rs b/src/client_server/membership.rs
index 9285648cb776cd2bfe13207469fd5696b5ac8f43..8d1940243a429f21e2c9b24ebfb6b76bdd694519 100644
--- a/src/client_server/membership.rs
+++ b/src/client_server/membership.rs
@@ -19,7 +19,7 @@
     },
     events::pdu::Pdu,
     events::{room::member, EventType},
-    EventId, Raw, RoomId, RoomVersionId, UserId,
+    EventId, Raw, RoomId, RoomVersionId, ServerName, UserId,
 };
 use state_res::StateEvent;
 use std::{
@@ -41,6 +41,7 @@ pub async fn join_room_by_id_route(
         &db,
         body.sender_id.as_ref(),
         &body.room_id,
+        &[body.room_id.server_name().to_owned()],
         body.third_party_signed.as_ref(),
     )
     .await
@@ -54,13 +55,12 @@ pub async fn join_room_by_id_or_alias_route(
     db: State<'_, Database>,
     body: Ruma<join_room_by_id_or_alias::Request<'_>>,
 ) -> ConduitResult<join_room_by_id_or_alias::Response> {
-    let room_id = match RoomId::try_from(body.room_id_or_alias.clone()) {
-        Ok(room_id) => room_id,
+    let (servers, room_id) = match RoomId::try_from(body.room_id_or_alias.clone()) {
+        Ok(room_id) => (vec![room_id.server_name().to_owned()], room_id),
         Err(room_alias) => {
-            client_server::get_alias_helper(&db, &room_alias)
-                .await?
-                .0
-                .room_id
+            let response = client_server::get_alias_helper(&db, &room_alias).await?;
+
+            (response.0.servers, response.0.room_id)
         }
     };
 
@@ -69,6 +69,7 @@ pub async fn join_room_by_id_or_alias_route(
             &db,
             body.sender_id.as_ref(),
             &room_id,
+            &servers,
             body.third_party_signed.as_ref(),
         )
         .await?
@@ -415,22 +416,37 @@ async fn join_room_by_id_helper(
     db: &Database,
     sender_id: Option<&UserId>,
     room_id: &RoomId,
+    servers: &[Box<ServerName>],
     _third_party_signed: Option<&IncomingThirdPartySigned>,
 ) -> ConduitResult<join_room_by_id::Response> {
     let sender_id = sender_id.expect("user is authenticated");
 
     // Ask a remote server if we don't have this room
     if !db.rooms.exists(&room_id)? && room_id.server_name() != db.globals.server_name() {
-        let make_join_response = server_server::send_request(
-            &db,
-            room_id.server_name().to_string(),
-            federation::membership::create_join_event_template::v1::Request {
-                room_id,
-                user_id: sender_id,
-                ver: &[RoomVersionId::Version5, RoomVersionId::Version6],
-            },
-        )
-        .await?;
+        let mut make_join_response_and_server = Err(Error::BadServerResponse(
+            "No server available to assist in joining.",
+        ));
+
+        for remote_server in servers {
+            let make_join_response = server_server::send_request(
+                &db,
+                remote_server,
+                federation::membership::create_join_event_template::v1::Request {
+                    room_id,
+                    user_id: sender_id,
+                    ver: &[RoomVersionId::Version5, RoomVersionId::Version6],
+                },
+            )
+            .await;
+
+            make_join_response_and_server = make_join_response.map(|r| (r, remote_server));
+
+            if make_join_response_and_server.is_ok() {
+                break;
+            }
+        }
+
+        let (make_join_response, remote_server) = make_join_response_and_server?;
 
         let mut join_event_stub_value =
             serde_json::from_str::<serde_json::Value>(make_join_response.event.json().get())
@@ -475,7 +491,7 @@ async fn join_room_by_id_helper(
 
         let send_join_response = server_server::send_request(
             &db,
-            room_id.server_name().to_string(),
+            remote_server,
             federation::membership::create_join_event::v2::Request {
                 room_id,
                 event_id: &event_id,
diff --git a/src/server_server.rs b/src/server_server.rs
index 6634d5a22cac50eb1e5e36b4f31712a35dbf319e..fc1da001d218493676f134fc4783be34bd625adf 100644
--- a/src/server_server.rs
+++ b/src/server_server.rs
@@ -13,7 +13,7 @@
         },
         OutgoingRequest,
     },
-    EventId,
+    EventId, ServerName,
 };
 use serde_json::json;
 use std::{
@@ -44,16 +44,16 @@ pub async fn request_well_known(db: &crate::Database, destination: &str) -> Opti
 
 pub async fn send_request<T: OutgoingRequest>(
     db: &crate::Database,
-    destination: String,
+    destination: &ServerName,
     request: T,
 ) -> Result<T::IncomingResponse>
 where
     T: Debug,
 {
     let actual_destination = "https://".to_owned()
-        + &request_well_known(db, &destination)
+        + &request_well_known(db, &destination.as_str())
             .await
-            .unwrap_or(destination.clone() + ":8448");
+            .unwrap_or(destination.as_str().to_owned() + ":8448");
 
     let mut http_request = request
         .try_into_http_request(&actual_destination, Some(""))
@@ -82,7 +82,7 @@ pub async fn send_request<T: OutgoingRequest>(
         "origin".to_owned(),
         db.globals.server_name().as_str().into(),
     );
-    request_map.insert("destination".to_owned(), destination.into());
+    request_map.insert("destination".to_owned(), destination.as_str().into());
 
     let mut request_json = request_map.into();
     ruma::signatures::sign_json(