diff --git a/Cargo.lock b/Cargo.lock
index 9682f2fe..8b25b478 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1516,12 +1516,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "paste"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
-
 [[package]]
 name = "pear"
 version = "0.2.3"
@@ -1990,7 +1984,7 @@ dependencies = [
 [[package]]
 name = "ruma"
 version = "0.4.0"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "assign",
  "js_int",
@@ -2011,7 +2005,7 @@ dependencies = [
 [[package]]
 name = "ruma-api"
 version = "0.18.5"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "bytes",
  "http",
@@ -2027,7 +2021,7 @@ dependencies = [
 [[package]]
 name = "ruma-api-macros"
 version = "0.18.5"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "proc-macro-crate",
  "proc-macro2",
@@ -2038,7 +2032,7 @@ dependencies = [
 [[package]]
 name = "ruma-appservice-api"
 version = "0.4.0"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "ruma-api",
  "ruma-common",
@@ -2052,7 +2046,7 @@ dependencies = [
 [[package]]
 name = "ruma-client-api"
 version = "0.12.3"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "assign",
  "bytes",
@@ -2072,7 +2066,7 @@ dependencies = [
 [[package]]
 name = "ruma-common"
 version = "0.6.0"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "indexmap",
  "js_int",
@@ -2087,7 +2081,7 @@ dependencies = [
 [[package]]
 name = "ruma-events"
 version = "0.24.6"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "indoc",
  "js_int",
@@ -2103,7 +2097,7 @@ dependencies = [
 [[package]]
 name = "ruma-events-macros"
 version = "0.24.6"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "proc-macro-crate",
  "proc-macro2",
@@ -2114,7 +2108,7 @@ dependencies = [
 [[package]]
 name = "ruma-federation-api"
 version = "0.3.1"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "js_int",
  "ruma-api",
@@ -2129,9 +2123,8 @@ dependencies = [
 [[package]]
 name = "ruma-identifiers"
 version = "0.20.0"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
- "paste",
  "percent-encoding",
  "rand 0.8.4",
  "ruma-identifiers-macros",
@@ -2144,7 +2137,7 @@ dependencies = [
 [[package]]
 name = "ruma-identifiers-macros"
 version = "0.20.0"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "quote",
  "ruma-identifiers-validation",
@@ -2154,7 +2147,7 @@ dependencies = [
 [[package]]
 name = "ruma-identifiers-validation"
 version = "0.5.0"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "thiserror",
 ]
@@ -2162,7 +2155,7 @@ dependencies = [
 [[package]]
 name = "ruma-identity-service-api"
 version = "0.3.0"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "js_int",
  "ruma-api",
@@ -2175,7 +2168,7 @@ dependencies = [
 [[package]]
 name = "ruma-push-gateway-api"
 version = "0.3.0"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "js_int",
  "ruma-api",
@@ -2190,7 +2183,7 @@ dependencies = [
 [[package]]
 name = "ruma-serde"
 version = "0.5.0"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "bytes",
  "form_urlencoded",
@@ -2204,7 +2197,7 @@ dependencies = [
 [[package]]
 name = "ruma-serde-macros"
 version = "0.5.0"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "proc-macro-crate",
  "proc-macro2",
@@ -2215,7 +2208,7 @@ dependencies = [
 [[package]]
 name = "ruma-signatures"
 version = "0.9.0"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "base64 0.13.0",
  "ed25519-dalek",
@@ -2232,7 +2225,7 @@ dependencies = [
 [[package]]
 name = "ruma-state-res"
 version = "0.4.1"
-source = "git+https://github.com/ruma/ruma?rev=e7f01ca55a1eff437bad754bf0554cc09f44ec2a#e7f01ca55a1eff437bad754bf0554cc09f44ec2a"
+source = "git+https://github.com/ruma/ruma?rev=bba7d624425da2c65a834bbd0e633b7577488cdf#bba7d624425da2c65a834bbd0e633b7577488cdf"
 dependencies = [
  "itertools 0.10.1",
  "js_int",
diff --git a/Cargo.toml b/Cargo.toml
index 91c7e259..b24afb5c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,7 +19,7 @@ rocket = { version = "0.5.0-rc.1", features = ["tls"] } # Used to handle request
 
 # Used for matrix spec type definitions and helpers
 #ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
-ruma = { git = "https://github.com/ruma/ruma", rev = "e7f01ca55a1eff437bad754bf0554cc09f44ec2a", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
+ruma = { git = "https://github.com/ruma/ruma", rev = "bba7d624425da2c65a834bbd0e633b7577488cdf", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
 #ruma = { git = "https://github.com/timokoesters/ruma", rev = "50c1db7e0a3a21fc794b0cce3b64285a4c750c71", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
 #ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
 
diff --git a/src/client_server/account.rs b/src/client_server/account.rs
index 4b3ad0d4..3149187f 100644
--- a/src/client_server/account.rs
+++ b/src/client_server/account.rs
@@ -1,8 +1,4 @@
-use std::{
-    collections::BTreeMap,
-    convert::{TryFrom, TryInto},
-    sync::Arc,
-};
+use std::{collections::BTreeMap, convert::TryInto, sync::Arc};
 
 use super::{DEVICE_ID_LENGTH, SESSION_ID_LENGTH, TOKEN_LENGTH};
 use crate::{database::DatabaseGuard, pdu::PduBuilder, utils, ConduitResult, Error, Ruma};
@@ -11,10 +7,9 @@ use ruma::{
         error::ErrorKind,
         r0::{
             account::{
-                change_password, deactivate, get_username_availability, register, whoami,
-                ThirdPartyIdRemovalStatus,
+                change_password, deactivate, get_3pids, get_username_availability, register,
+                whoami, ThirdPartyIdRemovalStatus,
             },
-            contact::get_contacts,
             uiaa::{AuthFlow, AuthType, UiaaInfo},
         },
     },
@@ -282,7 +277,7 @@ pub async fn register_route(
         let mut content = RoomCreateEventContent::new(conduit_user.clone());
         content.federate = true;
         content.predecessor = None;
-        content.room_version = RoomVersionId::Version6;
+        content.room_version = RoomVersionId::V6;
 
         // 1. The room create event
         db.rooms.build_and_append_pdu(
@@ -397,9 +392,8 @@ pub async fn register_route(
         )?;
 
         // 6. Events implied by name and topic
-        let room_name =
-            Box::<RoomName>::try_from(format!("{} Admin Room", db.globals.server_name()))
-                .expect("Room name is valid");
+        let room_name = RoomName::parse(format!("{} Admin Room", db.globals.server_name()))
+            .expect("Room name is valid");
         db.rooms.build_and_append_pdu(
             PduBuilder {
                 event_type: EventType::RoomName,
@@ -433,7 +427,7 @@ pub async fn register_route(
         )?;
 
         // Room alias
-        let alias: RoomAliasId = format!("#admins:{}", db.globals.server_name())
+        let alias: Box<RoomAliasId> = format!("#admins:{}", db.globals.server_name())
             .try_into()
             .expect("#admins:server_name is a valid alias name");
 
@@ -757,9 +751,9 @@ pub async fn deactivate_route(
     get("/_matrix/client/r0/account/3pid", data = "<body>")
 )]
 pub async fn third_party_route(
-    body: Ruma<get_contacts::Request>,
-) -> ConduitResult<get_contacts::Response> {
+    body: Ruma<get_3pids::Request>,
+) -> ConduitResult<get_3pids::Response> {
     let _sender_user = body.sender_user.as_ref().expect("user is authenticated");
 
-    Ok(get_contacts::Response::new(Vec::new()).into())
+    Ok(get_3pids::Response::new(Vec::new()).into())
 }
diff --git a/src/client_server/capabilities.rs b/src/client_server/capabilities.rs
index f86b23b5..c69b7cb2 100644
--- a/src/client_server/capabilities.rs
+++ b/src/client_server/capabilities.rs
@@ -22,12 +22,12 @@ pub async fn get_capabilities_route(
     _body: Ruma<get_capabilities::Request>,
 ) -> ConduitResult<get_capabilities::Response> {
     let mut available = BTreeMap::new();
-    available.insert(RoomVersionId::Version5, RoomVersionStability::Stable);
-    available.insert(RoomVersionId::Version6, RoomVersionStability::Stable);
+    available.insert(RoomVersionId::V5, RoomVersionStability::Stable);
+    available.insert(RoomVersionId::V6, RoomVersionStability::Stable);
 
     let mut capabilities = Capabilities::new();
     capabilities.room_versions = RoomVersionsCapability {
-        default: RoomVersionId::Version6,
+        default: RoomVersionId::V6,
         available,
     };
 
diff --git a/src/client_server/directory.rs b/src/client_server/directory.rs
index 490f7524..5a1bc494 100644
--- a/src/client_server/directory.rs
+++ b/src/client_server/directory.rs
@@ -167,7 +167,7 @@ pub(crate) async fn get_public_rooms_filtered_helper(
                 other_server,
                 federation::directory::get_public_rooms_filtered::v1::Request {
                     limit,
-                    since: since.as_deref(),
+                    since,
                     filter: Filter {
                         generic_search_term: filter.generic_search_term.as_deref(),
                     },
diff --git a/src/client_server/keys.rs b/src/client_server/keys.rs
index a44f5e9c..08ea6e76 100644
--- a/src/client_server/keys.rs
+++ b/src/client_server/keys.rs
@@ -316,7 +316,7 @@ pub async fn get_key_changes_route(
 
 pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
     sender_user: Option<&UserId>,
-    device_keys_input: &BTreeMap<UserId, Vec<Box<DeviceId>>>,
+    device_keys_input: &BTreeMap<Box<UserId>, Vec<Box<DeviceId>>>,
     allowed_signatures: F,
     db: &Database,
 ) -> Result<get_keys::Response> {
@@ -328,6 +328,8 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
     let mut get_over_federation = HashMap::new();
 
     for (user_id, device_ids) in device_keys_input {
+        let user_id: &UserId = &**user_id;
+
         if user_id.server_name() != db.globals.server_name() {
             get_over_federation
                 .entry(user_id.server_name())
@@ -355,11 +357,11 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
                     container.insert(device_id, keys);
                 }
             }
-            device_keys.insert(user_id.clone(), container);
+            device_keys.insert(user_id.to_owned(), container);
         } else {
             for device_id in device_ids {
                 let mut container = BTreeMap::new();
-                if let Some(mut keys) = db.users.get_device_keys(&user_id.clone(), device_id)? {
+                if let Some(mut keys) = db.users.get_device_keys(user_id, device_id)? {
                     let metadata = db.users.get_device_metadata(user_id, device_id)?.ok_or(
                         Error::BadRequest(
                             ErrorKind::InvalidParam,
@@ -371,24 +373,24 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
                         device_display_name: metadata.display_name,
                     };
 
-                    container.insert(device_id.clone(), keys);
+                    container.insert(device_id.to_owned(), keys);
                 }
-                device_keys.insert(user_id.clone(), container);
+                device_keys.insert(user_id.to_owned(), container);
             }
         }
 
         if let Some(master_key) = db.users.get_master_key(user_id, &allowed_signatures)? {
-            master_keys.insert(user_id.clone(), master_key);
+            master_keys.insert(user_id.to_owned(), master_key);
         }
         if let Some(self_signing_key) = db
             .users
             .get_self_signing_key(user_id, &allowed_signatures)?
         {
-            self_signing_keys.insert(user_id.clone(), self_signing_key);
+            self_signing_keys.insert(user_id.to_owned(), self_signing_key);
         }
         if Some(user_id) == sender_user {
             if let Some(user_signing_key) = db.users.get_user_signing_key(user_id)? {
-                user_signing_keys.insert(user_id.clone(), user_signing_key);
+                user_signing_keys.insert(user_id.to_owned(), user_signing_key);
             }
         }
     }
@@ -400,7 +402,7 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
         .map(|(server, vec)| async move {
             let mut device_keys_input_fed = BTreeMap::new();
             for (user_id, keys) in vec {
-                device_keys_input_fed.insert(user_id.clone(), keys.clone());
+                device_keys_input_fed.insert(user_id.to_owned(), keys.clone());
             }
             (
                 server,
@@ -440,7 +442,7 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
 }
 
 pub(crate) async fn claim_keys_helper(
-    one_time_keys_input: &BTreeMap<UserId, BTreeMap<Box<DeviceId>, DeviceKeyAlgorithm>>,
+    one_time_keys_input: &BTreeMap<Box<UserId>, BTreeMap<Box<DeviceId>, DeviceKeyAlgorithm>>,
     db: &Database,
 ) -> Result<claim_keys::Response> {
     let mut one_time_keys = BTreeMap::new();
diff --git a/src/client_server/membership.rs b/src/client_server/membership.rs
index ec685ec9..e28f9a31 100644
--- a/src/client_server/membership.rs
+++ b/src/client_server/membership.rs
@@ -31,6 +31,7 @@ use serde_json::value::{to_raw_value, RawValue as RawJsonValue};
 use std::{
     collections::{hash_map::Entry, BTreeMap, HashMap, HashSet},
     convert::{TryFrom, TryInto},
+    iter,
     sync::{Arc, RwLock},
     time::{Duration, Instant},
 };
@@ -64,7 +65,7 @@ pub async fn join_room_by_id_route(
         .filter_map(|event| serde_json::from_str(event.json().get()).ok())
         .filter_map(|event: serde_json::Value| event.get("sender").cloned())
         .filter_map(|sender| sender.as_str().map(|s| s.to_owned()))
-        .filter_map(|sender| UserId::try_from(sender).ok())
+        .filter_map(|sender| UserId::parse(sender).ok())
         .map(|user| user.server_name().to_owned())
         .collect();
 
@@ -72,7 +73,7 @@ pub async fn join_room_by_id_route(
 
     let ret = join_room_by_id_helper(
         &db,
-        body.sender_user.as_ref(),
+        body.sender_user.as_deref(),
         &body.room_id,
         &servers,
         body.third_party_signed.as_ref(),
@@ -99,9 +100,10 @@ pub async fn join_room_by_id_or_alias_route(
     db: DatabaseGuard,
     body: Ruma<join_room_by_id_or_alias::Request<'_>>,
 ) -> ConduitResult<join_room_by_id_or_alias::Response> {
-    let sender_user = body.sender_user.as_ref().expect("user is authenticated");
+    let sender_user = body.sender_user.as_deref().expect("user is authenticated");
+    let body = body.body;
 
-    let (servers, room_id) = match RoomId::try_from(body.room_id_or_alias.clone()) {
+    let (servers, room_id) = match Box::<RoomId>::try_from(body.room_id_or_alias) {
         Ok(room_id) => {
             let mut servers: HashSet<_> = db
                 .rooms
@@ -111,7 +113,7 @@ pub async fn join_room_by_id_or_alias_route(
                 .filter_map(|event| serde_json::from_str(event.json().get()).ok())
                 .filter_map(|event: serde_json::Value| event.get("sender").cloned())
                 .filter_map(|sender| sender.as_str().map(|s| s.to_owned()))
-                .filter_map(|sender| UserId::try_from(sender).ok())
+                .filter_map(|sender| UserId::parse(sender).ok())
                 .map(|user| user.server_name().to_owned())
                 .collect();
 
@@ -127,7 +129,7 @@ pub async fn join_room_by_id_or_alias_route(
 
     let join_room_response = join_room_by_id_helper(
         &db,
-        body.sender_user.as_ref(),
+        Some(sender_user),
         &room_id,
         &servers,
         body.third_party_signed.as_ref(),
@@ -531,7 +533,7 @@ async fn join_room_by_id_helper(
             .roomid_mutex_state
             .write()
             .unwrap()
-            .entry(room_id.clone())
+            .entry(room_id.to_owned())
             .or_default(),
     );
     let state_lock = mutex_state.lock().await;
@@ -551,7 +553,7 @@ async fn join_room_by_id_helper(
                     federation::membership::create_join_event_template::v1::Request {
                         room_id,
                         user_id: sender_user,
-                        ver: &[RoomVersionId::Version5, RoomVersionId::Version6],
+                        ver: &[RoomVersionId::V5, RoomVersionId::V6],
                     },
                 )
                 .await;
@@ -567,8 +569,7 @@ async fn join_room_by_id_helper(
 
         let room_version = match make_join_response.room_version {
             Some(room_version)
-                if room_version == RoomVersionId::Version5
-                    || room_version == RoomVersionId::Version6 =>
+                if room_version == RoomVersionId::V5 || room_version == RoomVersionId::V6 =>
             {
                 room_version
             }
@@ -620,12 +621,13 @@ async fn join_room_by_id_helper(
         .expect("event is valid, we just created it");
 
         // Generate event id
-        let event_id = EventId::try_from(&*format!(
+        let event_id = format!(
             "${}",
             ruma::signatures::reference_hash(&join_event_stub, &room_version)
                 .expect("ruma can calculate reference hashes")
-        ))
-        .expect("ruma's reference hashes are valid event ids");
+        );
+        let event_id = <&EventId>::try_from(event_id.as_str())
+            .expect("ruma's reference hashes are valid event ids");
 
         // Add event_id back
         join_event_stub.insert(
@@ -643,7 +645,7 @@ async fn join_room_by_id_helper(
                 remote_server,
                 federation::membership::create_join_event::v2::Request {
                     room_id,
-                    event_id: &event_id,
+                    event_id,
                     pdu: &PduEvent::convert_to_outgoing_federation_event(join_event.clone()),
                 },
             )
@@ -651,7 +653,7 @@ async fn join_room_by_id_helper(
 
         db.rooms.get_or_create_shortroomid(room_id, &db.globals)?;
 
-        let pdu = PduEvent::from_id_val(&event_id, join_event.clone())
+        let pdu = PduEvent::from_id_val(event_id, join_event.clone())
             .map_err(|_| Error::BadServerResponse("Invalid join event PDU."))?;
 
         let mut state = HashMap::new();
@@ -739,7 +741,7 @@ async fn join_room_by_id_helper(
         db.rooms.append_pdu(
             &pdu,
             utils::to_canonical_object(&pdu).expect("Pdu is valid canonical object"),
-            &[pdu.event_id.clone()],
+            iter::once(&*pdu.event_id),
             db,
         )?;
 
@@ -776,7 +778,7 @@ async fn join_room_by_id_helper(
 
     db.flush()?;
 
-    Ok(join_room_by_id::Response::new(room_id.clone()).into())
+    Ok(join_room_by_id::Response::new(room_id.to_owned()).into())
 }
 
 fn validate_and_add_event_id(
@@ -784,12 +786,12 @@ fn validate_and_add_event_id(
     room_version: &RoomVersionId,
     pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, String>>>,
     db: &Database,
-) -> Result<(EventId, CanonicalJsonObject)> {
+) -> Result<(Box<EventId>, CanonicalJsonObject)> {
     let mut value: CanonicalJsonObject = serde_json::from_str(pdu.get()).map_err(|e| {
         error!("Invalid PDU in server response: {:?}: {:?}", pdu, e);
         Error::BadServerResponse("Invalid PDU in server response")
     })?;
-    let event_id = EventId::try_from(&*format!(
+    let event_id = EventId::parse(format!(
         "${}",
         ruma::signatures::reference_hash(&value, room_version)
             .expect("ruma can calculate reference hashes")
@@ -856,7 +858,7 @@ pub(crate) async fn invite_helper<'a>(
                     .roomid_mutex_state
                     .write()
                     .unwrap()
-                    .entry(room_id.clone())
+                    .entry(room_id.to_owned())
                     .or_default(),
             );
             let state_lock = mutex_state.lock().await;
@@ -892,9 +894,7 @@ pub(crate) async fn invite_helper<'a>(
 
             // If there was no create event yet, assume we are creating a version 6 room right now
             let room_version_id = create_event_content
-                .map_or(RoomVersionId::Version6, |create_event| {
-                    create_event.room_version
-                });
+                .map_or(RoomVersionId::V6, |create_event| create_event.room_version);
             let room_version =
                 RoomVersion::new(&room_version_id).expect("room version is supported");
 
@@ -939,9 +939,9 @@ pub(crate) async fn invite_helper<'a>(
             }
 
             let pdu = PduEvent {
-                event_id: ruma::event_id!("$thiswillbefilledinlater"),
-                room_id: room_id.clone(),
-                sender: sender_user.clone(),
+                event_id: ruma::event_id!("$thiswillbefilledinlater").to_owned(),
+                room_id: room_id.to_owned(),
+                sender: sender_user.to_owned(),
                 origin_server_ts: utils::millis_since_unix_epoch()
                     .try_into()
                     .expect("time is valid"),
@@ -1014,12 +1014,13 @@ pub(crate) async fn invite_helper<'a>(
         };
 
         // Generate event id
-        let expected_event_id = EventId::try_from(&*format!(
+        let expected_event_id = format!(
             "${}",
             ruma::signatures::reference_hash(&pdu_json, &room_version_id)
                 .expect("ruma can calculate reference hashes")
-        ))
-        .expect("ruma's reference hashes are valid event ids");
+        );
+        let expected_event_id = <&EventId>::try_from(expected_event_id.as_str())
+            .expect("ruma's reference hashes are valid event ids");
 
         let response = db
             .sending
@@ -1028,7 +1029,7 @@ pub(crate) async fn invite_helper<'a>(
                 user_id.server_name(),
                 create_invite::v2::Request {
                     room_id,
-                    event_id: &expected_event_id,
+                    event_id: expected_event_id,
                     room_version: &room_version_id,
                     event: &PduEvent::convert_to_outgoing_federation_event(pdu_json.clone()),
                     invite_room_state: &invite_room_state,
@@ -1100,7 +1101,7 @@ pub(crate) async fn invite_helper<'a>(
             .roomid_mutex_state
             .write()
             .unwrap()
-            .entry(room_id.clone())
+            .entry(room_id.to_owned())
             .or_default(),
     );
     let state_lock = mutex_state.lock().await;
diff --git a/src/client_server/message.rs b/src/client_server/message.rs
index abbbe8ea..e5219433 100644
--- a/src/client_server/message.rs
+++ b/src/client_server/message.rs
@@ -5,13 +5,8 @@ use ruma::{
         r0::message::{get_message_events, send_message_event},
     },
     events::EventType,
-    EventId,
-};
-use std::{
-    collections::BTreeMap,
-    convert::{TryFrom, TryInto},
-    sync::Arc,
 };
+use std::{collections::BTreeMap, convert::TryInto, sync::Arc};
 
 #[cfg(feature = "conduit_bin")]
 use rocket::{get, put};
@@ -67,11 +62,10 @@ pub async fn send_message_event_route(
             ));
         }
 
-        let event_id = EventId::try_from(
-            utils::string_from_bytes(&response)
-                .map_err(|_| Error::bad_database("Invalid txnid bytes in database."))?,
-        )
-        .map_err(|_| Error::bad_database("Invalid event id in txnid data."))?;
+        let event_id = utils::string_from_bytes(&response)
+            .map_err(|_| Error::bad_database("Invalid txnid bytes in database."))?
+            .try_into()
+            .map_err(|_| Error::bad_database("Invalid event id in txnid data."))?;
         return Ok(send_message_event::Response { event_id }.into());
     }
 
diff --git a/src/client_server/push.rs b/src/client_server/push.rs
index 64f27f1c..a8ba1a2a 100644
--- a/src/client_server/push.rs
+++ b/src/client_server/push.rs
@@ -105,15 +105,15 @@ pub async fn get_pushrule_route(
 /// Creates a single specified push rule for this user.
 #[cfg_attr(
     feature = "conduit_bin",
-    put("/_matrix/client/r0/pushrules/<_>/<_>/<_>", data = "<req>")
+    put("/_matrix/client/r0/pushrules/<_>/<_>/<_>", data = "<body>")
 )]
-#[tracing::instrument(skip(db, req))]
+#[tracing::instrument(skip(db, body))]
 pub async fn set_pushrule_route(
     db: DatabaseGuard,
-    req: Ruma<set_pushrule::Request<'_>>,
+    body: Ruma<set_pushrule::Request<'_>>,
 ) -> ConduitResult<set_pushrule::Response> {
-    let sender_user = req.sender_user.as_ref().expect("user is authenticated");
-    let body = req.body;
+    let sender_user = body.sender_user.as_ref().expect("user is authenticated");
+    let body = body.body;
 
     if body.scope != "global" {
         return Err(Error::BadRequest(
diff --git a/src/client_server/report.rs b/src/client_server/report.rs
index 3dcb4d1c..ae069849 100644
--- a/src/client_server/report.rs
+++ b/src/client_server/report.rs
@@ -1,8 +1,11 @@
-use crate::{database::admin::AdminCommand, database::DatabaseGuard, ConduitResult, Error, Ruma};
+use crate::{
+    database::{admin::AdminCommand, DatabaseGuard},
+    ConduitResult, Error, Ruma,
+};
 use ruma::{
     api::client::{error::ErrorKind, r0::room::report_content},
     events::room::message,
-    Int,
+    int,
 };
 
 #[cfg(feature = "conduit_bin")]
@@ -33,7 +36,7 @@ pub async fn report_event_route(
         }
     };
 
-    if body.score > Int::from(0) || body.score < Int::from(-100) {
+    if body.score > int!(0) || body.score < int!(-100) {
         return Err(Error::BadRequest(
             ErrorKind::InvalidParam,
             "Invalid score, must be within 0 to -100",
@@ -57,8 +60,7 @@ pub async fn report_event_route(
                 Report Score: {}\n\
                 Report Reason: {}",
                 sender_user, pdu.event_id, pdu.room_id, pdu.sender, body.score, body.reason
-            )
-            .to_owned(),
+            ),
             format!(
                 "<details><summary>Report received from: <a href=\"https://matrix.to/#/{0}\">{0}\
                 </a></summary><ul><li>Event Info<ul><li>Event ID: <code>{1}</code>\
@@ -72,8 +74,7 @@ pub async fn report_event_route(
                 pdu.sender,
                 body.score,
                 RawStr::new(&body.reason).html_escape()
-            )
-            .to_owned(),
+            ),
         ),
     ));
 
diff --git a/src/client_server/room.rs b/src/client_server/room.rs
index 47c7ee6f..83571f1d 100644
--- a/src/client_server/room.rs
+++ b/src/client_server/room.rs
@@ -26,12 +26,7 @@ use ruma::{
     RoomAliasId, RoomId, RoomVersionId,
 };
 use serde_json::{json, value::to_raw_value};
-use std::{
-    cmp::max,
-    collections::BTreeMap,
-    convert::{TryFrom, TryInto},
-    sync::Arc,
-};
+use std::{cmp::max, collections::BTreeMap, convert::TryInto, sync::Arc};
 use tracing::{info, warn};
 
 #[cfg(feature = "conduit_bin")]
@@ -88,14 +83,16 @@ pub async fn create_room_route(
         ));
     }
 
-    let alias: Option<RoomAliasId> =
+    let alias: Option<Box<RoomAliasId>> =
         body.room_alias_name
             .as_ref()
             .map_or(Ok(None), |localpart| {
                 // TODO: Check for invalid characters and maximum length
                 let alias =
-                    RoomAliasId::try_from(format!("#{}:{}", localpart, db.globals.server_name()))
-                        .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid alias."))?;
+                    RoomAliasId::parse(format!("#{}:{}", localpart, db.globals.server_name()))
+                        .map_err(|_| {
+                            Error::BadRequest(ErrorKind::InvalidParam, "Invalid alias.")
+                        })?;
 
                 if db.rooms.id_from_alias(&alias)?.is_some() {
                     Err(Error::BadRequest(
@@ -109,7 +106,7 @@ pub async fn create_room_route(
 
     let room_version = match body.room_version.clone() {
         Some(room_version) => {
-            if room_version == RoomVersionId::Version5 || room_version == RoomVersionId::Version6 {
+            if room_version == RoomVersionId::V5 || room_version == RoomVersionId::V6 {
                 room_version
             } else {
                 return Err(Error::BadRequest(
@@ -118,7 +115,7 @@ pub async fn create_room_route(
                 ));
             }
         }
-        None => RoomVersionId::Version6,
+        None => RoomVersionId::V6,
     };
 
     let content = match &body.creation_content {
@@ -164,7 +161,7 @@ pub async fn create_room_route(
             .get(),
     );
 
-    if let Err(_) = de_result {
+    if de_result.is_err() {
         return Err(Error::BadRequest(
             ErrorKind::BadJson,
             "Invalid creation content",
@@ -269,7 +266,7 @@ pub async fn create_room_route(
             PduBuilder {
                 event_type: EventType::RoomCanonicalAlias,
                 content: to_raw_value(&RoomCanonicalAliasEventContent {
-                    alias: Some(room_alias_id.clone()),
+                    alias: Some(room_alias_id.to_owned()),
                     alt_aliases: vec![],
                 })
                 .expect("We checked that alias earlier, it must be fine"),
@@ -505,10 +502,7 @@ pub async fn upgrade_room_route(
 ) -> ConduitResult<upgrade_room::Response> {
     let sender_user = body.sender_user.as_ref().expect("user is authenticated");
 
-    if !matches!(
-        body.new_version,
-        RoomVersionId::Version5 | RoomVersionId::Version6
-    ) {
+    if !matches!(body.new_version, RoomVersionId::V5 | RoomVersionId::V6) {
         return Err(Error::BadRequest(
             ErrorKind::UnsupportedRoomVersion,
             "This server does not support that room version.",
@@ -605,7 +599,7 @@ pub async fn upgrade_room_route(
             .get(),
     );
 
-    if let Err(_) = de_result {
+    if de_result.is_err() {
         return Err(Error::BadRequest(
             ErrorKind::BadJson,
             "Error forming creation event",
diff --git a/src/client_server/state.rs b/src/client_server/state.rs
index 307bccab..0ba20620 100644
--- a/src/client_server/state.rs
+++ b/src/client_server/state.rs
@@ -267,7 +267,7 @@ async fn send_state_event_for_key_helper(
     event_type: EventType,
     json: &Raw<AnyStateEventContent>,
     state_key: String,
-) -> Result<EventId> {
+) -> Result<Box<EventId>> {
     let sender_user = sender;
 
     // TODO: Review this check, error if event is unparsable, use event type, allow alias if it
@@ -303,7 +303,7 @@ async fn send_state_event_for_key_helper(
             .roomid_mutex_state
             .write()
             .unwrap()
-            .entry(room_id.clone())
+            .entry(room_id.to_owned())
             .or_default(),
     );
     let state_lock = mutex_state.lock().await;
diff --git a/src/client_server/sync.rs b/src/client_server/sync.rs
index 65c07bc9..9ba3b7fb 100644
--- a/src/client_server/sync.rs
+++ b/src/client_server/sync.rs
@@ -10,7 +10,7 @@ use ruma::{
 };
 use std::{
     collections::{hash_map::Entry, BTreeMap, HashMap, HashSet},
-    convert::{TryFrom, TryInto},
+    convert::TryInto,
     sync::Arc,
     time::Duration,
 };
@@ -61,8 +61,9 @@ pub async fn sync_events_route(
     db: DatabaseGuard,
     body: Ruma<sync_events::Request<'_>>,
 ) -> Result<RumaResponse<sync_events::Response>, RumaResponse<UiaaResponse>> {
-    let sender_user = body.sender_user.as_ref().expect("user is authenticated");
-    let sender_device = body.sender_device.as_ref().expect("user is authenticated");
+    let sender_user = body.sender_user.expect("user is authenticated");
+    let sender_device = body.sender_device.expect("user is authenticated");
+    let body = body.body;
 
     let arc_db = Arc::new(db);
 
@@ -132,7 +133,7 @@ pub async fn sync_events_route(
 
 async fn sync_helper_wrapper(
     db: Arc<DatabaseGuard>,
-    sender_user: UserId,
+    sender_user: Box<UserId>,
     sender_device: Box<DeviceId>,
     since: Option<String>,
     full_state: bool,
@@ -176,7 +177,7 @@ async fn sync_helper_wrapper(
 
 async fn sync_helper(
     db: Arc<DatabaseGuard>,
-    sender_user: UserId,
+    sender_user: Box<UserId>,
     sender_device: Box<DeviceId>,
     since: Option<String>,
     full_state: bool,
@@ -296,7 +297,7 @@ async fn sync_helper(
                             })?;
 
                         if let Some(state_key) = &pdu.state_key {
-                            let user_id = UserId::try_from(state_key.clone()).map_err(|_| {
+                            let user_id = UserId::parse(state_key.clone()).map_err(|_| {
                                 Error::bad_database("Invalid UserId in member PDU.")
                             })?;
 
@@ -424,7 +425,7 @@ async fn sync_helper(
                     }
 
                     if let Some(state_key) = &state_event.state_key {
-                        let user_id = UserId::try_from(state_key.clone())
+                        let user_id = UserId::parse(state_key.clone())
                             .map_err(|_| Error::bad_database("Invalid UserId in member PDU."))?;
 
                         if user_id == sender_user {
@@ -793,7 +794,7 @@ fn share_encrypted_room(
 ) -> Result<bool> {
     Ok(db
         .rooms
-        .get_shared_rooms(vec![sender_user.clone(), user_id.clone()])?
+        .get_shared_rooms(vec![sender_user.to_owned(), user_id.to_owned()])?
         .filter_map(|r| r.ok())
         .filter(|room_id| room_id != ignore_room)
         .filter_map(|other_room_id| {
diff --git a/src/client_server/voip.rs b/src/client_server/voip.rs
index 9c3b20d4..66a85f0f 100644
--- a/src/client_server/voip.rs
+++ b/src/client_server/voip.rs
@@ -26,7 +26,7 @@ pub async fn turn_server_route(
 
     let turn_secret = db.globals.turn_secret();
 
-    let (username, password) = if turn_secret != "" {
+    let (username, password) = if !turn_secret.is_empty() {
         let expiry = SecondsSinceUnixEpoch::from_system_time(
             SystemTime::now() + Duration::from_secs(db.globals.turn_ttl()),
         )
@@ -49,8 +49,8 @@ pub async fn turn_server_route(
     };
 
     Ok(get_turn_server_info::Response {
-        username: username,
-        password: password,
+        username,
+        password,
         uris: db.globals.turn_uris().to_vec(),
         ttl: Duration::from_secs(db.globals.turn_ttl()),
     }
diff --git a/src/database.rs b/src/database.rs
index 080e24b3..84ca68dc 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -476,10 +476,9 @@ impl Database {
             if db.globals.database_version()? < 6 {
                 // Set room member count
                 for (roomid, _) in db.rooms.roomid_shortstatehash.iter() {
-                    let room_id =
-                        RoomId::try_from(utils::string_from_bytes(&roomid).unwrap()).unwrap();
-
-                    db.rooms.update_joined_count(&room_id, &db)?;
+                    let string = utils::string_from_bytes(&roomid).unwrap();
+                    let room_id = <&RoomId>::try_from(string.as_str()).unwrap();
+                    db.rooms.update_joined_count(room_id, &db)?;
                 }
 
                 db.globals.bump_database_version(6)?;
@@ -489,7 +488,7 @@ impl Database {
 
             if db.globals.database_version()? < 7 {
                 // Upgrade state store
-                let mut last_roomstates: HashMap<RoomId, u64> = HashMap::new();
+                let mut last_roomstates: HashMap<Box<RoomId>, u64> = HashMap::new();
                 let mut current_sstatehash: Option<u64> = None;
                 let mut current_room = None;
                 let mut current_state = HashSet::new();
@@ -570,7 +569,7 @@ impl Database {
                         if let Some(current_sstatehash) = current_sstatehash {
                             handle_state(
                                 current_sstatehash,
-                                current_room.as_ref().unwrap(),
+                                current_room.as_deref().unwrap(),
                                 current_state,
                                 &mut last_roomstates,
                             )?;
@@ -586,10 +585,9 @@ impl Database {
                             .get(&seventid)
                             .unwrap()
                             .unwrap();
-                        let event_id =
-                            EventId::try_from(utils::string_from_bytes(&event_id).unwrap())
-                                .unwrap();
-                        let pdu = db.rooms.get_pdu(&event_id).unwrap().unwrap();
+                        let string = utils::string_from_bytes(&event_id).unwrap();
+                        let event_id = <&EventId>::try_from(string.as_str()).unwrap();
+                        let pdu = db.rooms.get_pdu(event_id).unwrap().unwrap();
 
                         if Some(&pdu.room_id) != current_room.as_ref() {
                             current_room = Some(pdu.room_id.clone());
@@ -604,7 +602,7 @@ impl Database {
                 if let Some(current_sstatehash) = current_sstatehash {
                     handle_state(
                         current_sstatehash,
-                        current_room.as_ref().unwrap(),
+                        current_room.as_deref().unwrap(),
                         current_state,
                         &mut last_roomstates,
                     )?;
diff --git a/src/database/admin.rs b/src/database/admin.rs
index 8d8559a5..1e5c47c9 100644
--- a/src/database/admin.rs
+++ b/src/database/admin.rs
@@ -1,7 +1,4 @@
-use std::{
-    convert::{TryFrom, TryInto},
-    sync::Arc,
-};
+use std::{convert::TryInto, sync::Arc};
 
 use crate::{pdu::PduBuilder, Database};
 use rocket::futures::{channel::mpsc, stream::StreamExt};
@@ -36,14 +33,14 @@ impl Admin {
 
             let guard = db.read().await;
 
-            let conduit_user =
-                UserId::try_from(format!("@conduit:{}", guard.globals.server_name()))
-                    .expect("@conduit:server_name is valid");
+            let conduit_user = UserId::parse(format!("@conduit:{}", guard.globals.server_name()))
+                .expect("@conduit:server_name is valid");
 
             let conduit_room = guard
                 .rooms
                 .id_from_alias(
-                    &format!("#admins:{}", guard.globals.server_name())
+                    format!("#admins:{}", guard.globals.server_name())
+                        .as_str()
                         .try_into()
                         .expect("#admins:server_name is a valid room alias"),
                 )
diff --git a/src/database/globals.rs b/src/database/globals.rs
index 05ecb568..098d8197 100644
--- a/src/database/globals.rs
+++ b/src/database/globals.rs
@@ -40,13 +40,13 @@ pub struct Globals {
     dns_resolver: TokioAsyncResolver,
     jwt_decoding_key: Option<jsonwebtoken::DecodingKey<'static>>,
     pub(super) server_signingkeys: Arc<dyn Tree>,
-    pub bad_event_ratelimiter: Arc<RwLock<HashMap<EventId, RateLimitState>>>,
+    pub bad_event_ratelimiter: Arc<RwLock<HashMap<Box<EventId>, RateLimitState>>>,
     pub bad_signature_ratelimiter: Arc<RwLock<HashMap<Vec<String>, RateLimitState>>>,
     pub servername_ratelimiter: Arc<RwLock<HashMap<Box<ServerName>, Arc<Semaphore>>>>,
-    pub sync_receivers: RwLock<HashMap<(UserId, Box<DeviceId>), SyncHandle>>,
-    pub roomid_mutex_insert: RwLock<HashMap<RoomId, Arc<Mutex<()>>>>,
-    pub roomid_mutex_state: RwLock<HashMap<RoomId, Arc<TokioMutex<()>>>>,
-    pub roomid_mutex_federation: RwLock<HashMap<RoomId, Arc<TokioMutex<()>>>>, // this lock will be held longer
+    pub sync_receivers: RwLock<HashMap<(Box<UserId>, Box<DeviceId>), SyncHandle>>,
+    pub roomid_mutex_insert: RwLock<HashMap<Box<RoomId>, Arc<Mutex<()>>>>,
+    pub roomid_mutex_state: RwLock<HashMap<Box<RoomId>, Arc<TokioMutex<()>>>>,
+    pub roomid_mutex_federation: RwLock<HashMap<Box<RoomId>, Arc<TokioMutex<()>>>>, // this lock will be held longer
     pub rotate: RotationHandler,
 }
 
@@ -254,7 +254,7 @@ impl Globals {
         &self,
         origin: &ServerName,
         new_keys: ServerSigningKeys,
-    ) -> Result<BTreeMap<ServerSigningKeyId, VerifyKey>> {
+    ) -> Result<BTreeMap<Box<ServerSigningKeyId>, VerifyKey>> {
         // Not atomic, but this is not critical
         let signingkeys = self.server_signingkeys.get(origin.as_bytes())?;
 
@@ -293,7 +293,7 @@ impl Globals {
     pub fn signing_keys_for(
         &self,
         origin: &ServerName,
-    ) -> Result<BTreeMap<ServerSigningKeyId, VerifyKey>> {
+    ) -> Result<BTreeMap<Box<ServerSigningKeyId>, VerifyKey>> {
         let signingkeys = self
             .server_signingkeys
             .get(origin.as_bytes())?
diff --git a/src/database/key_backups.rs b/src/database/key_backups.rs
index 98ea0111..56963c08 100644
--- a/src/database/key_backups.rs
+++ b/src/database/key_backups.rs
@@ -6,7 +6,7 @@ use ruma::{
     },
     RoomId, UserId,
 };
-use std::{collections::BTreeMap, convert::TryFrom, sync::Arc};
+use std::{collections::BTreeMap, sync::Arc};
 
 use super::abstraction::Tree;
 
@@ -209,13 +209,13 @@ impl KeyBackups {
         &self,
         user_id: &UserId,
         version: &str,
-    ) -> Result<BTreeMap<RoomId, RoomKeyBackup>> {
+    ) -> Result<BTreeMap<Box<RoomId>, RoomKeyBackup>> {
         let mut prefix = user_id.as_bytes().to_vec();
         prefix.push(0xff);
         prefix.extend_from_slice(version.as_bytes());
         prefix.push(0xff);
 
-        let mut rooms = BTreeMap::<RoomId, RoomKeyBackup>::new();
+        let mut rooms = BTreeMap::<Box<RoomId>, RoomKeyBackup>::new();
 
         for result in self
             .backupkeyid_backup
@@ -231,7 +231,7 @@ impl KeyBackups {
                         Error::bad_database("backupkeyid_backup session_id is invalid.")
                     })?;
 
-                let room_id = RoomId::try_from(
+                let room_id = RoomId::parse(
                     utils::string_from_bytes(parts.next().ok_or_else(|| {
                         Error::bad_database("backupkeyid_backup key is invalid.")
                     })?)
diff --git a/src/database/pusher.rs b/src/database/pusher.rs
index f53f137b..97ca85d8 100644
--- a/src/database/pusher.rs
+++ b/src/database/pusher.rs
@@ -234,7 +234,7 @@ pub fn get_actions<'a>(
     db: &Database,
 ) -> Result<&'a [Action]> {
     let ctx = PushConditionRoomCtx {
-        room_id: room_id.clone(),
+        room_id: room_id.to_owned(),
         member_count: 10_u32.into(), // TODO: get member count efficiently
         user_display_name: db
             .users
@@ -277,7 +277,7 @@ async fn send_notice(
     let mut data_minus_url = pusher.data.clone();
     // The url must be stripped off according to spec
     data_minus_url.url = None;
-    device.data = Some(data_minus_url);
+    device.data = data_minus_url;
 
     // Tweaks are only added if the format is NOT event_id_only
     if !event_id_only {
diff --git a/src/database/rooms.rs b/src/database/rooms.rs
index c5b795bd..4c092bf7 100644
--- a/src/database/rooms.rs
+++ b/src/database/rooms.rs
@@ -36,6 +36,8 @@ use std::{
     borrow::Cow,
     collections::{BTreeMap, HashMap, HashSet},
     convert::{TryFrom, TryInto},
+    fmt::Debug,
+    iter,
     mem::size_of,
     sync::{Arc, Mutex, RwLock},
     time::Instant,
@@ -107,14 +109,14 @@ pub struct Rooms {
     /// RoomId + EventId -> Parent PDU EventId.
     pub(super) referencedevents: Arc<dyn Tree>,
 
-    pub(super) pdu_cache: Mutex<LruCache<EventId, Arc<PduEvent>>>,
+    pub(super) pdu_cache: Mutex<LruCache<Box<EventId>, Arc<PduEvent>>>,
     pub(super) shorteventid_cache: Mutex<LruCache<u64, Arc<EventId>>>,
     pub(super) auth_chain_cache: Mutex<LruCache<Vec<u64>, Arc<HashSet<u64>>>>,
-    pub(super) eventidshort_cache: Mutex<LruCache<EventId, u64>>,
+    pub(super) eventidshort_cache: Mutex<LruCache<Box<EventId>, u64>>,
     pub(super) statekeyshort_cache: Mutex<LruCache<(EventType, String), u64>>,
     pub(super) shortstatekey_cache: Mutex<LruCache<u64, (EventType, String)>>,
-    pub(super) our_real_users_cache: RwLock<HashMap<RoomId, Arc<HashSet<UserId>>>>,
-    pub(super) appservice_in_room_cache: RwLock<HashMap<RoomId, HashMap<String, bool>>>,
+    pub(super) our_real_users_cache: RwLock<HashMap<Box<RoomId>, Arc<HashSet<Box<UserId>>>>>,
+    pub(super) appservice_in_room_cache: RwLock<HashMap<Box<RoomId>, HashMap<String, bool>>>,
     pub(super) stateinfo_cache: Mutex<
         LruCache<
             u64,
@@ -434,7 +436,7 @@ impl Rooms {
                 None => continue,
             };
 
-            let user_id = match UserId::try_from(state_key) {
+            let user_id = match UserId::parse(state_key) {
                 Ok(id) => id,
                 Err(_) => continue,
             };
@@ -742,7 +744,7 @@ impl Rooms {
         self.eventidshort_cache
             .lock()
             .unwrap()
-            .insert(event_id.clone(), short);
+            .insert(event_id.to_owned(), short);
 
         Ok(short)
     }
@@ -871,12 +873,10 @@ impl Rooms {
             .get(&shorteventid.to_be_bytes())?
             .ok_or_else(|| Error::bad_database("Shorteventid does not exist"))?;
 
-        let event_id = Arc::new(
-            EventId::try_from(utils::string_from_bytes(&bytes).map_err(|_| {
-                Error::bad_database("EventID in shorteventid_eventid is invalid unicode.")
-            })?)
-            .map_err(|_| Error::bad_database("EventId in shorteventid_eventid is invalid."))?,
-        );
+        let event_id = EventId::parse_arc(utils::string_from_bytes(&bytes).map_err(|_| {
+            Error::bad_database("EventID in shorteventid_eventid is invalid unicode.")
+        })?)
+        .map_err(|_| Error::bad_database("EventId in shorteventid_eventid is invalid."))?;
 
         self.shorteventid_cache
             .lock()
@@ -1112,7 +1112,7 @@ impl Rooms {
             self.pdu_cache
                 .lock()
                 .unwrap()
-                .insert(event_id.clone(), Arc::clone(&pdu));
+                .insert(event_id.to_owned(), Arc::clone(&pdu));
             Ok(Some(pdu))
         } else {
             Ok(None)
@@ -1162,14 +1162,14 @@ impl Rooms {
 
     /// Returns the leaf pdus of a room.
     #[tracing::instrument(skip(self))]
-    pub fn get_pdu_leaves(&self, room_id: &RoomId) -> Result<HashSet<EventId>> {
+    pub fn get_pdu_leaves(&self, room_id: &RoomId) -> Result<HashSet<Box<EventId>>> {
         let mut prefix = room_id.as_bytes().to_vec();
         prefix.push(0xff);
 
         self.roomid_pduleaves
             .scan_prefix(prefix)
             .map(|(_, bytes)| {
-                EventId::try_from(utils::string_from_bytes(&bytes).map_err(|_| {
+                EventId::parse(utils::string_from_bytes(&bytes).map_err(|_| {
                     Error::bad_database("EventID in roomid_pduleaves is invalid unicode.")
                 })?)
                 .map_err(|_| Error::bad_database("EventId in roomid_pduleaves is invalid."))
@@ -1178,7 +1178,7 @@ impl Rooms {
     }
 
     #[tracing::instrument(skip(self, room_id, event_ids))]
-    pub fn mark_as_referenced(&self, room_id: &RoomId, event_ids: &[EventId]) -> Result<()> {
+    pub fn mark_as_referenced(&self, room_id: &RoomId, event_ids: &[Box<EventId>]) -> Result<()> {
         for prev in event_ids {
             let mut key = room_id.as_bytes().to_vec();
             key.extend_from_slice(prev.as_bytes());
@@ -1193,7 +1193,11 @@ impl Rooms {
     /// The provided `event_ids` become the new leaves, this allows a room to have multiple
     /// `prev_events`.
     #[tracing::instrument(skip(self))]
-    pub fn replace_pdu_leaves(&self, room_id: &RoomId, event_ids: &[EventId]) -> Result<()> {
+    pub fn replace_pdu_leaves<'a>(
+        &self,
+        room_id: &RoomId,
+        event_ids: impl IntoIterator<Item = &'a EventId> + Debug,
+    ) -> Result<()> {
         let mut prefix = room_id.as_bytes().to_vec();
         prefix.push(0xff);
 
@@ -1257,11 +1261,11 @@ impl Rooms {
     ///
     /// Returns pdu id
     #[tracing::instrument(skip(self, pdu, pdu_json, leaves, db))]
-    pub fn append_pdu(
+    pub fn append_pdu<'a>(
         &self,
         pdu: &PduEvent,
         mut pdu_json: CanonicalJsonObject,
-        leaves: &[EventId],
+        leaves: impl IntoIterator<Item = &'a EventId> + Debug,
         db: &Database,
     ) -> Result<Vec<u8>> {
         let shortroomid = self.get_shortroomid(&pdu.room_id)?.expect("room exists");
@@ -1420,7 +1424,7 @@ impl Rooms {
                     }
 
                     // if the state_key fails
-                    let target_user_id = UserId::try_from(state_key.clone())
+                    let target_user_id = UserId::parse(state_key.clone())
                         .expect("This state_key was previously validated");
 
                     let content = serde_json::from_str::<ExtractMembership>(pdu.content.get())
@@ -1476,9 +1480,10 @@ impl Rooms {
                     if body.starts_with(&format!("@conduit:{}: ", db.globals.server_name()))
                         && self
                             .id_from_alias(
-                                &format!("#admins:{}", db.globals.server_name())
-                                    .try_into()
-                                    .expect("#admins:server_name is a valid room alias"),
+                                <&RoomAliasId>::try_from(
+                                    format!("#admins:{}", db.globals.server_name()).as_str(),
+                                )
+                                .expect("#admins:server_name is a valid room alias"),
                             )?
                             .as_ref()
                             == Some(&pdu.room_id)
@@ -1528,7 +1533,7 @@ impl Rooms {
                                 }
                                 "get_auth_chain" => {
                                     if args.len() == 1 {
-                                        if let Ok(event_id) = EventId::try_from(args[0]) {
+                                        if let Ok(event_id) = EventId::parse_arc(args[0]) {
                                             if let Some(event) = db.rooms.get_pdu_json(&event_id)? {
                                                 let room_id_str = event
                                                     .get("room_id")
@@ -1539,12 +1544,12 @@ impl Rooms {
                                                         )
                                                     })?;
 
-                                                let room_id = RoomId::try_from(room_id_str)
-                                                .map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
+                                                let room_id = <&RoomId>::try_from(room_id_str)
+                                                    .map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
                                                 let start = Instant::now();
                                                 let count = server_server::get_auth_chain(
-                                                    &room_id,
-                                                    vec![Arc::new(event_id)],
+                                                    room_id,
+                                                    vec![event_id],
                                                     db,
                                                 )?
                                                 .count();
@@ -1567,12 +1572,12 @@ impl Rooms {
                                         let string = body[1..body.len() - 1].join("\n");
                                         match serde_json::from_str(&string) {
                                             Ok(value) => {
-                                                let event_id = EventId::try_from(&*format!(
+                                                let event_id = EventId::parse(format!(
                                                     "${}",
                                                     // Anything higher than version3 behaves the same
                                                     ruma::signatures::reference_hash(
                                                         &value,
-                                                        &RoomVersionId::Version6
+                                                        &RoomVersionId::V6
                                                     )
                                                     .expect("ruma can calculate reference hashes")
                                                 ))
@@ -1622,7 +1627,7 @@ impl Rooms {
                                 }
                                 "get_pdu" => {
                                     if args.len() == 1 {
-                                        if let Ok(event_id) = EventId::try_from(args[0]) {
+                                        if let Ok(event_id) = EventId::parse(args[0]) {
                                             let mut outlier = false;
                                             let mut pdu_json =
                                                 db.rooms.get_non_outlier_pdu_json(&event_id)?;
@@ -1948,7 +1953,7 @@ impl Rooms {
         room_id: &RoomId,
         db: &Database,
         _mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room mutex
-    ) -> Result<EventId> {
+    ) -> Result<Box<EventId>> {
         let PduBuilder {
             event_type,
             content,
@@ -1985,9 +1990,7 @@ impl Rooms {
 
         // If there was no create event yet, assume we are creating a version 6 room right now
         let room_version_id = create_event_content
-            .map_or(RoomVersionId::Version6, |create_event| {
-                create_event.room_version
-            });
+            .map_or(RoomVersionId::V6, |create_event| create_event.room_version);
         let room_version = RoomVersion::new(&room_version_id).expect("room version is supported");
 
         let auth_events =
@@ -2016,9 +2019,9 @@ impl Rooms {
         }
 
         let mut pdu = PduEvent {
-            event_id: ruma::event_id!("$thiswillbefilledinlater"),
-            room_id: room_id.clone(),
-            sender: sender.clone(),
+            event_id: ruma::event_id!("$thiswillbefilledinlater").to_owned(),
+            room_id: room_id.to_owned(),
+            sender: sender.to_owned(),
             origin_server_ts: utils::millis_since_unix_epoch()
                 .try_into()
                 .expect("time is valid"),
@@ -2083,7 +2086,7 @@ impl Rooms {
         .expect("event is valid, we just created it");
 
         // Generate event id
-        pdu.event_id = EventId::try_from(&*format!(
+        pdu.event_id = EventId::parse(format!(
             "${}",
             ruma::signatures::reference_hash(&pdu_json, &room_version_id)
                 .expect("ruma can calculate reference hashes")
@@ -2107,7 +2110,7 @@ impl Rooms {
             pdu_json,
             // Since this PDU references all pdu_leaves we can update the leaves
             // of the room
-            &[pdu.event_id.clone()],
+            iter::once(&*pdu.event_id),
             db,
         )?;
 
@@ -2206,7 +2209,7 @@ impl Rooms {
         let mut first_pdu_id = prefix.clone();
         first_pdu_id.extend_from_slice(&(since + 1).to_be_bytes());
 
-        let user_id = user_id.clone();
+        let user_id = user_id.to_owned();
 
         Ok(self
             .pduid_pdu
@@ -2243,7 +2246,7 @@ impl Rooms {
 
         let current: &[u8] = &current;
 
-        let user_id = user_id.clone();
+        let user_id = user_id.to_owned();
 
         Ok(self
             .pduid_pdu
@@ -2280,7 +2283,7 @@ impl Rooms {
 
         let current: &[u8] = &current;
 
-        let user_id = user_id.clone();
+        let user_id = user_id.to_owned();
 
         Ok(self
             .pduid_pdu
@@ -2412,7 +2415,7 @@ impl Rooms {
 
                             for room_ids in direct_event.content.0.values_mut() {
                                 if room_ids.iter().any(|r| r == &predecessor.room_id) {
-                                    room_ids.push(room_id.clone());
+                                    room_ids.push(room_id.to_owned());
                                     room_ids_updated = true;
                                 }
                             }
@@ -2451,7 +2454,11 @@ impl Rooms {
                         EventType::IgnoredUserList,
                     )?
                     .map_or(false, |ignored| {
-                        ignored.content.ignored_users.contains(sender)
+                        ignored
+                            .content
+                            .ignored_users
+                            .iter()
+                            .any(|user| user == sender)
                     });
 
                 if is_ignored {
@@ -2537,7 +2544,7 @@ impl Rooms {
         self.our_real_users_cache
             .write()
             .unwrap()
-            .insert(room_id.clone(), Arc::new(real_users));
+            .insert(room_id.to_owned(), Arc::new(real_users));
 
         for old_joined_server in self.room_servers(room_id).filter_map(|r| r.ok()) {
             if !joined_servers.remove(&old_joined_server) {
@@ -2582,7 +2589,7 @@ impl Rooms {
         &self,
         room_id: &RoomId,
         db: &Database,
-    ) -> Result<Arc<HashSet<UserId>>> {
+    ) -> Result<Arc<HashSet<Box<UserId>>>> {
         let maybe = self
             .our_real_users_cache
             .read()
@@ -2650,7 +2657,7 @@ impl Rooms {
             self.appservice_in_room_cache
                 .write()
                 .unwrap()
-                .entry(room_id.clone())
+                .entry(room_id.to_owned())
                 .or_default()
                 .insert(appservice.0.clone(), in_room);
 
@@ -2694,7 +2701,7 @@ impl Rooms {
                     .roomid_mutex_state
                     .write()
                     .unwrap()
-                    .entry(room_id.clone())
+                    .entry(room_id.to_owned())
                     .or_default(),
             );
             let state_lock = mutex_state.lock().await;
@@ -2754,7 +2761,7 @@ impl Rooms {
             .filter_map(|event| serde_json::from_str(event.json().get()).ok())
             .filter_map(|event: serde_json::Value| event.get("sender").cloned())
             .filter_map(|sender| sender.as_str().map(|s| s.to_owned()))
-            .filter_map(|sender| UserId::try_from(sender).ok())
+            .filter_map(|sender| UserId::parse(sender).ok())
             .map(|user| user.server_name().to_owned())
             .collect();
 
@@ -2778,9 +2785,7 @@ impl Rooms {
         let (make_leave_response, remote_server) = make_leave_response_and_server?;
 
         let room_version_id = match make_leave_response.room_version {
-            Some(version)
-                if version == RoomVersionId::Version5 || version == RoomVersionId::Version6 =>
-            {
+            Some(version) if version == RoomVersionId::V5 || version == RoomVersionId::V6 => {
                 version
             }
             _ => return Err(Error::BadServerResponse("Room version is not supported")),
@@ -2817,7 +2822,7 @@ impl Rooms {
         .expect("event is valid, we just created it");
 
         // Generate event id
-        let event_id = EventId::try_from(&*format!(
+        let event_id = EventId::parse(format!(
             "${}",
             ruma::signatures::reference_hash(&leave_event_stub, &room_version_id)
                 .expect("ruma can calculate reference hashes")
@@ -2902,11 +2907,11 @@ impl Rooms {
     }
 
     #[tracing::instrument(skip(self))]
-    pub fn id_from_alias(&self, alias: &RoomAliasId) -> Result<Option<RoomId>> {
+    pub fn id_from_alias(&self, alias: &RoomAliasId) -> Result<Option<Box<RoomId>>> {
         self.alias_roomid
             .get(alias.alias().as_bytes())?
             .map(|bytes| {
-                RoomId::try_from(utils::string_from_bytes(&bytes).map_err(|_| {
+                RoomId::parse(utils::string_from_bytes(&bytes).map_err(|_| {
                     Error::bad_database("Room ID in alias_roomid is invalid unicode.")
                 })?)
                 .map_err(|_| Error::bad_database("Room ID in alias_roomid is invalid."))
@@ -2918,7 +2923,7 @@ impl Rooms {
     pub fn room_aliases<'a>(
         &'a self,
         room_id: &RoomId,
-    ) -> impl Iterator<Item = Result<RoomAliasId>> + 'a {
+    ) -> impl Iterator<Item = Result<Box<RoomAliasId>>> + 'a {
         let mut prefix = room_id.as_bytes().to_vec();
         prefix.push(0xff);
 
@@ -2947,9 +2952,9 @@ impl Rooms {
     }
 
     #[tracing::instrument(skip(self))]
-    pub fn public_rooms(&self) -> impl Iterator<Item = Result<RoomId>> + '_ {
+    pub fn public_rooms(&self) -> impl Iterator<Item = Result<Box<RoomId>>> + '_ {
         self.publicroomids.iter().map(|(bytes, _)| {
-            RoomId::try_from(
+            RoomId::parse(
                 utils::string_from_bytes(&bytes).map_err(|_| {
                     Error::bad_database("Room ID in publicroomids is invalid unicode.")
                 })?,
@@ -3009,8 +3014,8 @@ impl Rooms {
     #[tracing::instrument(skip(self))]
     pub fn get_shared_rooms<'a>(
         &'a self,
-        users: Vec<UserId>,
-    ) -> Result<impl Iterator<Item = Result<RoomId>> + 'a> {
+        users: Vec<Box<UserId>>,
+    ) -> Result<impl Iterator<Item = Result<Box<RoomId>>> + 'a> {
         let iterators = users.into_iter().map(move |user_id| {
             let mut prefix = user_id.as_bytes().to_vec();
             prefix.push(0xff);
@@ -3037,7 +3042,7 @@ impl Rooms {
         Ok(utils::common_elements(iterators, Ord::cmp)
             .expect("users is not empty")
             .map(|bytes| {
-                RoomId::try_from(utils::string_from_bytes(&*bytes).map_err(|_| {
+                RoomId::parse(utils::string_from_bytes(&*bytes).map_err(|_| {
                     Error::bad_database("Invalid RoomId bytes in userroomid_joined")
                 })?)
                 .map_err(|_| Error::bad_database("Invalid RoomId in userroomid_joined."))
@@ -3054,7 +3059,7 @@ impl Rooms {
         prefix.push(0xff);
 
         self.roomserverids.scan_prefix(prefix).map(|(key, _)| {
-            Box::<ServerName>::try_from(
+            ServerName::parse(
                 utils::string_from_bytes(
                     key.rsplit(|&b| b == 0xff)
                         .next()
@@ -3082,12 +3087,12 @@ impl Rooms {
     pub fn server_rooms<'a>(
         &'a self,
         server: &ServerName,
-    ) -> impl Iterator<Item = Result<RoomId>> + 'a {
+    ) -> impl Iterator<Item = Result<Box<RoomId>>> + 'a {
         let mut prefix = server.as_bytes().to_vec();
         prefix.push(0xff);
 
         self.serverroomids.scan_prefix(prefix).map(|(key, _)| {
-            RoomId::try_from(
+            RoomId::parse(
                 utils::string_from_bytes(
                     key.rsplit(|&b| b == 0xff)
                         .next()
@@ -3104,12 +3109,12 @@ impl Rooms {
     pub fn room_members<'a>(
         &'a self,
         room_id: &RoomId,
-    ) -> impl Iterator<Item = Result<UserId>> + 'a {
+    ) -> impl Iterator<Item = Result<Box<UserId>>> + 'a {
         let mut prefix = room_id.as_bytes().to_vec();
         prefix.push(0xff);
 
         self.roomuserid_joined.scan_prefix(prefix).map(|(key, _)| {
-            UserId::try_from(
+            UserId::parse(
                 utils::string_from_bytes(
                     key.rsplit(|&b| b == 0xff)
                         .next()
@@ -3150,14 +3155,14 @@ impl Rooms {
     pub fn room_useroncejoined<'a>(
         &'a self,
         room_id: &RoomId,
-    ) -> impl Iterator<Item = Result<UserId>> + 'a {
+    ) -> impl Iterator<Item = Result<Box<UserId>>> + 'a {
         let mut prefix = room_id.as_bytes().to_vec();
         prefix.push(0xff);
 
         self.roomuseroncejoinedids
             .scan_prefix(prefix)
             .map(|(key, _)| {
-                UserId::try_from(
+                UserId::parse(
                     utils::string_from_bytes(
                         key.rsplit(|&b| b == 0xff)
                             .next()
@@ -3176,14 +3181,14 @@ impl Rooms {
     pub fn room_members_invited<'a>(
         &'a self,
         room_id: &RoomId,
-    ) -> impl Iterator<Item = Result<UserId>> + 'a {
+    ) -> impl Iterator<Item = Result<Box<UserId>>> + 'a {
         let mut prefix = room_id.as_bytes().to_vec();
         prefix.push(0xff);
 
         self.roomuserid_invitecount
             .scan_prefix(prefix)
             .map(|(key, _)| {
-                UserId::try_from(
+                UserId::parse(
                     utils::string_from_bytes(
                         key.rsplit(|&b| b == 0xff)
                             .next()
@@ -3232,11 +3237,11 @@ impl Rooms {
     pub fn rooms_joined<'a>(
         &'a self,
         user_id: &UserId,
-    ) -> impl Iterator<Item = Result<RoomId>> + 'a {
+    ) -> impl Iterator<Item = Result<Box<RoomId>>> + 'a {
         self.userroomid_joined
             .scan_prefix(user_id.as_bytes().to_vec())
             .map(|(key, _)| {
-                RoomId::try_from(
+                RoomId::parse(
                     utils::string_from_bytes(
                         key.rsplit(|&b| b == 0xff)
                             .next()
@@ -3255,14 +3260,14 @@ impl Rooms {
     pub fn rooms_invited<'a>(
         &'a self,
         user_id: &UserId,
-    ) -> impl Iterator<Item = Result<(RoomId, Vec<Raw<AnyStrippedStateEvent>>)>> + 'a {
+    ) -> impl Iterator<Item = Result<(Box<RoomId>, Vec<Raw<AnyStrippedStateEvent>>)>> + 'a {
         let mut prefix = user_id.as_bytes().to_vec();
         prefix.push(0xff);
 
         self.userroomid_invitestate
             .scan_prefix(prefix)
             .map(|(key, state)| {
-                let room_id = RoomId::try_from(
+                let room_id = RoomId::parse(
                     utils::string_from_bytes(
                         key.rsplit(|&b| b == 0xff)
                             .next()
@@ -3328,14 +3333,14 @@ impl Rooms {
     pub fn rooms_left<'a>(
         &'a self,
         user_id: &UserId,
-    ) -> impl Iterator<Item = Result<(RoomId, Vec<Raw<AnySyncStateEvent>>)>> + 'a {
+    ) -> impl Iterator<Item = Result<(Box<RoomId>, Vec<Raw<AnySyncStateEvent>>)>> + 'a {
         let mut prefix = user_id.as_bytes().to_vec();
         prefix.push(0xff);
 
         self.userroomid_leftstate
             .scan_prefix(prefix)
             .map(|(key, state)| {
-                let room_id = RoomId::try_from(
+                let room_id = RoomId::parse(
                     utils::string_from_bytes(
                         key.rsplit(|&b| b == 0xff)
                             .next()
diff --git a/src/database/rooms/edus.rs b/src/database/rooms/edus.rs
index 9a27e437..eb2d3427 100644
--- a/src/database/rooms/edus.rs
+++ b/src/database/rooms/edus.rs
@@ -11,7 +11,7 @@ use ruma::{
 };
 use std::{
     collections::{HashMap, HashSet},
-    convert::{TryFrom, TryInto},
+    convert::TryInto,
     mem,
     sync::Arc,
 };
@@ -76,8 +76,13 @@ impl RoomEdus {
         &'a self,
         room_id: &RoomId,
         since: u64,
-    ) -> impl Iterator<Item = Result<(UserId, u64, Raw<ruma::events::AnySyncEphemeralRoomEvent>)>> + 'a
-    {
+    ) -> impl Iterator<
+        Item = Result<(
+            Box<UserId>,
+            u64,
+            Raw<ruma::events::AnySyncEphemeralRoomEvent>,
+        )>,
+    > + 'a {
         let mut prefix = room_id.as_bytes().to_vec();
         prefix.push(0xff);
         let prefix2 = prefix.clone();
@@ -92,7 +97,7 @@ impl RoomEdus {
                 let count =
                     utils::u64_from_bytes(&k[prefix.len()..prefix.len() + mem::size_of::<u64>()])
                         .map_err(|_| Error::bad_database("Invalid readreceiptid count in db."))?;
-                let user_id = UserId::try_from(
+                let user_id = UserId::parse(
                     utils::string_from_bytes(&k[prefix.len() + mem::size_of::<u64>() + 1..])
                         .map_err(|_| {
                             Error::bad_database("Invalid readreceiptid userid bytes in db.")
@@ -305,17 +310,13 @@ impl RoomEdus {
 
         let mut user_ids = HashSet::new();
 
-        for user_id in self
-            .typingid_userid
-            .scan_prefix(prefix)
-            .map(|(_, user_id)| {
-                UserId::try_from(utils::string_from_bytes(&user_id).map_err(|_| {
-                    Error::bad_database("User ID in typingid_userid is invalid unicode.")
-                })?)
-                .map_err(|_| Error::bad_database("User ID in typingid_userid is invalid."))
-            })
-        {
-            user_ids.insert(user_id?);
+        for (_, user_id) in self.typingid_userid.scan_prefix(prefix) {
+            let user_id = UserId::parse(utils::string_from_bytes(&user_id).map_err(|_| {
+                Error::bad_database("User ID in typingid_userid is invalid unicode.")
+            })?)
+            .map_err(|_| Error::bad_database("User ID in typingid_userid is invalid."))?;
+
+            user_ids.insert(user_id);
         }
 
         Ok(SyncEphemeralRoomEvent {
@@ -449,7 +450,7 @@ impl RoomEdus {
         {
             // Send new presence events to set the user offline
             let count = globals.next_count()?.to_be_bytes();
-            let user_id = utils::string_from_bytes(&user_id_bytes)
+            let user_id: Box<_> = utils::string_from_bytes(&user_id_bytes)
                 .map_err(|_| {
                     Error::bad_database("Invalid UserId bytes in userid_lastpresenceupdate.")
                 })?
@@ -475,7 +476,7 @@ impl RoomEdus {
                             presence: PresenceState::Offline,
                             status_msg: None,
                         },
-                        sender: user_id.clone(),
+                        sender: user_id.to_owned(),
                     })
                     .expect("PresenceEvent can be serialized"),
                 )?;
@@ -498,7 +499,7 @@ impl RoomEdus {
         since: u64,
         _rooms: &super::Rooms,
         _globals: &super::super::globals::Globals,
-    ) -> Result<HashMap<UserId, PresenceEvent>> {
+    ) -> Result<HashMap<Box<UserId>, PresenceEvent>> {
         //self.presence_maintain(rooms, globals)?;
 
         let mut prefix = room_id.as_bytes().to_vec();
@@ -513,7 +514,7 @@ impl RoomEdus {
             .iter_from(&*first_possible_edu, false)
             .take_while(|(key, _)| key.starts_with(&prefix))
         {
-            let user_id = UserId::try_from(
+            let user_id = UserId::parse(
                 utils::string_from_bytes(
                     key.rsplit(|&b| b == 0xff)
                         .next()
diff --git a/src/database/sending.rs b/src/database/sending.rs
index bf0cc2c1..1e180d43 100644
--- a/src/database/sending.rs
+++ b/src/database/sending.rs
@@ -1,6 +1,6 @@
 use std::{
     collections::{BTreeMap, HashMap, HashSet},
-    convert::{TryFrom, TryInto},
+    convert::TryInto,
     fmt::Debug,
     sync::Arc,
     time::{Duration, Instant},
@@ -397,7 +397,7 @@ impl Sending {
             // Because synapse resyncs, we can just insert dummy data
             let edu = Edu::DeviceListUpdate(DeviceListUpdateContent {
                 user_id,
-                device_id: device_id!("dummy"),
+                device_id: device_id!("dummy").to_owned(),
                 device_display_name: Some("Dummy".to_owned()),
                 stream_id: uint!(1),
                 prev_id: Vec::new(),
@@ -583,19 +583,18 @@ impl Sending {
                         }
                     }
 
-                    let userid =
-                        UserId::try_from(utils::string_from_bytes(user).map_err(|_| {
-                            (
-                                kind.clone(),
-                                Error::bad_database("Invalid push user string in db."),
-                            )
-                        })?)
-                        .map_err(|_| {
-                            (
-                                kind.clone(),
-                                Error::bad_database("Invalid push user id in db."),
-                            )
-                        })?;
+                    let userid = UserId::parse(utils::string_from_bytes(user).map_err(|_| {
+                        (
+                            kind.clone(),
+                            Error::bad_database("Invalid push user string in db."),
+                        )
+                    })?)
+                    .map_err(|_| {
+                        (
+                            kind.clone(),
+                            Error::bad_database("Invalid push user id in db."),
+                        )
+                    })?;
 
                     let mut senderkey = user.clone();
                     senderkey.push(0xff);
@@ -732,7 +731,7 @@ impl Sending {
             })?;
 
             (
-                OutgoingKind::Appservice(Box::<ServerName>::try_from(server).map_err(|_| {
+                OutgoingKind::Appservice(ServerName::parse(server).map_err(|_| {
                     Error::bad_database("Invalid server string in server_currenttransaction")
                 })?),
                 if value.is_empty() {
@@ -771,7 +770,7 @@ impl Sending {
             })?;
 
             (
-                OutgoingKind::Normal(Box::<ServerName>::try_from(server).map_err(|_| {
+                OutgoingKind::Normal(ServerName::parse(server).map_err(|_| {
                     Error::bad_database("Invalid server string in server_currenttransaction")
                 })?),
                 if value.is_empty() {
diff --git a/src/database/users.rs b/src/database/users.rs
index d0da0714..d4bf4890 100644
--- a/src/database/users.rs
+++ b/src/database/users.rs
@@ -8,7 +8,7 @@ use ruma::{
     DeviceId, DeviceKeyAlgorithm, DeviceKeyId, MilliSecondsSinceUnixEpoch, RoomAliasId, UInt,
     UserId,
 };
-use std::{collections::BTreeMap, convert::TryFrom, mem, sync::Arc};
+use std::{collections::BTreeMap, convert::TryInto, mem, sync::Arc};
 use tracing::warn;
 
 use super::abstraction::Tree;
@@ -62,12 +62,11 @@ impl Users {
         rooms: &super::rooms::Rooms,
         globals: &super::globals::Globals,
     ) -> Result<bool> {
-        let admin_room_alias_id =
-            RoomAliasId::try_from(format!("#admins:{}", globals.server_name()))
-                .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid alias."))?;
+        let admin_room_alias_id = RoomAliasId::parse(format!("#admins:{}", globals.server_name()))
+            .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid alias."))?;
         let admin_room_id = rooms.id_from_alias(&admin_room_alias_id)?.unwrap();
 
-        Ok(rooms.is_joined(user_id, &admin_room_id)?)
+        rooms.is_joined(user_id, &admin_room_id)
     }
 
     /// Create a new user account on this homeserver.
@@ -85,7 +84,7 @@ impl Users {
 
     /// Find out which user an access token belongs to.
     #[tracing::instrument(skip(self, token))]
-    pub fn find_from_token(&self, token: &str) -> Result<Option<(UserId, String)>> {
+    pub fn find_from_token(&self, token: &str) -> Result<Option<(Box<UserId>, String)>> {
         self.token_userdeviceid
             .get(token.as_bytes())?
             .map_or(Ok(None), |bytes| {
@@ -98,7 +97,7 @@ impl Users {
                 })?;
 
                 Ok(Some((
-                    UserId::try_from(utils::string_from_bytes(user_bytes).map_err(|_| {
+                    UserId::parse(utils::string_from_bytes(user_bytes).map_err(|_| {
                         Error::bad_database("User ID in token_userdeviceid is invalid unicode.")
                     })?)
                     .map_err(|_| {
@@ -113,9 +112,9 @@ impl Users {
 
     /// Returns an iterator over all users on this homeserver.
     #[tracing::instrument(skip(self))]
-    pub fn iter(&self) -> impl Iterator<Item = Result<UserId>> + '_ {
+    pub fn iter(&self) -> impl Iterator<Item = Result<Box<UserId>>> + '_ {
         self.userid_password.iter().map(|(bytes, _)| {
-            UserId::try_from(utils::string_from_bytes(&bytes).map_err(|_| {
+            UserId::parse(utils::string_from_bytes(&bytes).map_err(|_| {
                 Error::bad_database("User ID in userid_password is invalid unicode.")
             })?)
             .map_err(|_| Error::bad_database("User ID in userid_password is invalid."))
@@ -181,20 +180,21 @@ impl Users {
 
     /// Get the avatar_url of a user.
     #[tracing::instrument(skip(self, user_id))]
-    pub fn avatar_url(&self, user_id: &UserId) -> Result<Option<MxcUri>> {
+    pub fn avatar_url(&self, user_id: &UserId) -> Result<Option<Box<MxcUri>>> {
         self.userid_avatarurl
             .get(user_id.as_bytes())?
             .map(|bytes| {
                 let s = utils::string_from_bytes(&bytes)
                     .map_err(|_| Error::bad_database("Avatar URL in db is invalid."))?;
-                MxcUri::try_from(s).map_err(|_| Error::bad_database("Avatar URL in db is invalid."))
+                s.try_into()
+                    .map_err(|_| Error::bad_database("Avatar URL in db is invalid."))
             })
             .transpose()
     }
 
     /// Sets a new avatar_url or removes it if avatar_url is None.
     #[tracing::instrument(skip(self, user_id, avatar_url))]
-    pub fn set_avatar_url(&self, user_id: &UserId, avatar_url: Option<MxcUri>) -> Result<()> {
+    pub fn set_avatar_url(&self, user_id: &UserId, avatar_url: Option<Box<MxcUri>>) -> Result<()> {
         if let Some(avatar_url) = avatar_url {
             self.userid_avatarurl
                 .insert(user_id.as_bytes(), avatar_url.to_string().as_bytes())?;
@@ -409,7 +409,7 @@ impl Users {
         device_id: &DeviceId,
         key_algorithm: &DeviceKeyAlgorithm,
         globals: &super::globals::Globals,
-    ) -> Result<Option<(DeviceKeyId, OneTimeKey)>> {
+    ) -> Result<Option<(Box<DeviceKeyId>, OneTimeKey)>> {
         let mut prefix = user_id.as_bytes().to_vec();
         prefix.push(0xff);
         prefix.extend_from_slice(device_id.as_bytes());
@@ -459,7 +459,7 @@ impl Users {
                 .scan_prefix(userdeviceid)
                 .map(|(bytes, _)| {
                     Ok::<_, Error>(
-                        serde_json::from_slice::<DeviceKeyId>(
+                        serde_json::from_slice::<Box<DeviceKeyId>>(
                             &*bytes.rsplit(|&b| b == 0xff).next().ok_or_else(|| {
                                 Error::bad_database("OneTimeKey ID in db is invalid.")
                             })?,
@@ -632,7 +632,7 @@ impl Users {
             .ok_or_else(|| Error::bad_database("key in keyid_key has no signatures field."))?
             .as_object_mut()
             .ok_or_else(|| Error::bad_database("key in keyid_key has invalid signatures field."))?
-            .entry(sender_id.clone())
+            .entry(sender_id.to_owned())
             .or_insert_with(|| serde_json::Map::new().into());
 
         signatures
@@ -657,7 +657,7 @@ impl Users {
         user_or_room_id: &str,
         from: u64,
         to: Option<u64>,
-    ) -> impl Iterator<Item = Result<UserId>> + 'a {
+    ) -> impl Iterator<Item = Result<Box<UserId>>> + 'a {
         let mut prefix = user_or_room_id.as_bytes().to_vec();
         prefix.push(0xff);
 
@@ -683,7 +683,7 @@ impl Users {
                     }
             })
             .map(|(_, bytes)| {
-                UserId::try_from(utils::string_from_bytes(&bytes).map_err(|_| {
+                UserId::parse(utils::string_from_bytes(&bytes).map_err(|_| {
                     Error::bad_database("User ID in devicekeychangeid_userid is invalid unicode.")
                 })?)
                 .map_err(|_| Error::bad_database("User ID in devicekeychangeid_userid is invalid."))
diff --git a/src/pdu.rs b/src/pdu.rs
index 0f99f43b..c1f3d27d 100644
--- a/src/pdu.rs
+++ b/src/pdu.rs
@@ -13,7 +13,7 @@ use serde_json::{
     json,
     value::{to_raw_value, RawValue as RawJsonValue},
 };
-use std::{cmp::Ordering, collections::BTreeMap, convert::TryFrom};
+use std::{cmp::Ordering, collections::BTreeMap, convert::TryInto, ops::Deref};
 use tracing::warn;
 
 /// Content hashes of a PDU.
@@ -25,20 +25,20 @@ pub struct EventHash {
 
 #[derive(Clone, Deserialize, Serialize, Debug)]
 pub struct PduEvent {
-    pub event_id: EventId,
-    pub room_id: RoomId,
-    pub sender: UserId,
+    pub event_id: Box<EventId>,
+    pub room_id: Box<RoomId>,
+    pub sender: Box<UserId>,
     pub origin_server_ts: UInt,
     #[serde(rename = "type")]
     pub kind: EventType,
     pub content: Box<RawJsonValue>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub state_key: Option<String>,
-    pub prev_events: Vec<EventId>,
+    pub prev_events: Vec<Box<EventId>>,
     pub depth: UInt,
-    pub auth_events: Vec<EventId>,
+    pub auth_events: Vec<Box<EventId>>,
     #[serde(skip_serializing_if = "Option::is_none")]
-    pub redacts: Option<EventId>,
+    pub redacts: Option<Box<EventId>>,
     #[serde(default, skip_serializing_if = "Option::is_none")]
     pub unsigned: Option<Box<RawJsonValue>>,
     pub hashes: EventHash,
@@ -295,15 +295,15 @@ impl state_res::Event for PduEvent {
     }
 
     fn prev_events(&self) -> Box<dyn DoubleEndedIterator<Item = &EventId> + '_> {
-        Box::new(self.prev_events.iter())
+        Box::new(self.prev_events.iter().map(Deref::deref))
     }
 
     fn auth_events(&self) -> Box<dyn DoubleEndedIterator<Item = &EventId> + '_> {
-        Box::new(self.auth_events.iter())
+        Box::new(self.auth_events.iter().map(Deref::deref))
     }
 
     fn redacts(&self) -> Option<&EventId> {
-        self.redacts.as_ref()
+        self.redacts.as_deref()
     }
 }
 
@@ -331,18 +331,19 @@ impl Ord for PduEvent {
 /// Returns a tuple of the new `EventId` and the PDU as a `BTreeMap<String, CanonicalJsonValue>`.
 pub(crate) fn gen_event_id_canonical_json(
     pdu: &RawJsonValue,
-) -> crate::Result<(EventId, CanonicalJsonObject)> {
+) -> crate::Result<(Box<EventId>, CanonicalJsonObject)> {
     let value = serde_json::from_str(pdu.get()).map_err(|e| {
         warn!("Error parsing incoming event {:?}: {:?}", pdu, e);
         Error::BadServerResponse("Invalid PDU in server response")
     })?;
 
-    let event_id = EventId::try_from(&*format!(
+    let event_id = format!(
         "${}",
         // Anything higher than version3 behaves the same
-        ruma::signatures::reference_hash(&value, &RoomVersionId::Version6)
+        ruma::signatures::reference_hash(&value, &RoomVersionId::V6)
             .expect("ruma can calculate reference hashes")
-    ))
+    )
+    .try_into()
     .expect("ruma's reference hashes are valid event ids");
 
     Ok((event_id, value))
@@ -356,7 +357,7 @@ pub struct PduBuilder {
     pub content: Box<RawJsonValue>,
     pub unsigned: Option<BTreeMap<String, serde_json::Value>>,
     pub state_key: Option<String>,
-    pub redacts: Option<EventId>,
+    pub redacts: Option<Box<EventId>>,
 }
 
 /// Direct conversion prevents loss of the empty `state_key` that ruma requires.
diff --git a/src/ruma_wrapper.rs b/src/ruma_wrapper.rs
index 03c115cd..4b8d5dea 100644
--- a/src/ruma_wrapper.rs
+++ b/src/ruma_wrapper.rs
@@ -20,7 +20,6 @@ use {
     },
     ruma::api::{AuthScheme, IncomingRequest},
     std::collections::BTreeMap,
-    std::convert::TryFrom,
     std::io::Cursor,
     tracing::{debug, warn},
 };
@@ -29,7 +28,7 @@ use {
 /// first.
 pub struct Ruma<T: Outgoing> {
     pub body: T::Incoming,
-    pub sender_user: Option<UserId>,
+    pub sender_user: Option<Box<UserId>>,
     pub sender_device: Option<Box<DeviceId>>,
     pub sender_servername: Option<Box<ServerName>>,
     // This is None when body is not a valid string
@@ -86,7 +85,7 @@ where
                 registration
                     .get("as_token")
                     .and_then(|as_token| as_token.as_str())
-                    .map_or(false, |as_token| token.as_deref() == Some(as_token))
+                    .map_or(false, |as_token| token == Some(as_token))
             }) {
             match metadata.authentication {
                 AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => {
@@ -103,8 +102,7 @@ where
                             .unwrap()
                         },
                         |string| {
-                            UserId::try_from(string.expect("parsing to string always works"))
-                                .unwrap()
+                            UserId::parse(string.expect("parsing to string always works")).unwrap()
                         },
                     );
 
@@ -171,7 +169,7 @@ where
                         }
                     };
 
-                    let origin = match Box::<ServerName>::try_from(origin_str) {
+                    let origin = match ServerName::parse(origin_str) {
                         Ok(s) => s,
                         _ => {
                             warn!(
diff --git a/src/server_server.rs b/src/server_server.rs
index 482edf0f..ca6bb3fd 100644
--- a/src/server_server.rs
+++ b/src/server_server.rs
@@ -64,6 +64,7 @@ use std::{
     future::Future,
     mem,
     net::{IpAddr, SocketAddr},
+    ops::Deref,
     pin::Pin,
     sync::{Arc, RwLock, RwLockWriteGuard},
     time::{Duration, Instant, SystemTime},
@@ -396,10 +397,7 @@ async fn find_actual_destination(
                                         }
 
                                         if let Some(port) = force_port {
-                                            FedDest::Named(
-                                                delegated_hostname,
-                                                format!(":{}", port.to_string()),
-                                            )
+                                            FedDest::Named(delegated_hostname, format!(":{}", port))
                                         } else {
                                             add_port_to_hostname(&delegated_hostname)
                                         }
@@ -432,10 +430,7 @@ async fn find_actual_destination(
                                 }
 
                                 if let Some(port) = force_port {
-                                    FedDest::Named(
-                                        hostname.clone(),
-                                        format!(":{}", port.to_string()),
-                                    )
+                                    FedDest::Named(hostname.clone(), format!(":{}", port))
                                 } else {
                                     add_port_to_hostname(&hostname)
                                 }
@@ -550,12 +545,11 @@ pub fn get_server_keys_route(db: DatabaseGuard) -> Json<String> {
         return Json("Federation is disabled.".to_owned());
     }
 
-    let mut verify_keys = BTreeMap::new();
+    let mut verify_keys: BTreeMap<Box<ServerSigningKeyId>, VerifyKey> = BTreeMap::new();
     verify_keys.insert(
-        ServerSigningKeyId::try_from(
-            format!("ed25519:{}", db.globals.keypair().version()).as_str(),
-        )
-        .expect("found invalid server signing keys in DB"),
+        format!("ed25519:{}", db.globals.keypair().version())
+            .try_into()
+            .expect("found invalid server signing keys in DB"),
         VerifyKey {
             key: base64::encode_config(db.globals.keypair().public_key(), base64::STANDARD_NO_PAD),
         },
@@ -736,7 +730,7 @@ pub async fn send_transaction_message_route(
         // 0. Check the server is in the room
         let room_id = match value
             .get("room_id")
-            .and_then(|id| RoomId::try_from(id.as_str()?).ok())
+            .and_then(|id| RoomId::parse(id.as_str()?).ok())
         {
             Some(id) => id,
             None => {
@@ -1003,11 +997,10 @@ pub(crate) async fn handle_incoming_pdu<'a>(
     // 9. Fetch any missing prev events doing all checks listed here starting at 1. These are timeline events
     let mut graph = HashMap::new();
     let mut eventid_info = HashMap::new();
-    let mut todo_outlier_stack: Vec<_> = incoming_pdu
+    let mut todo_outlier_stack: Vec<Arc<EventId>> = incoming_pdu
         .prev_events
         .iter()
-        .cloned()
-        .map(Arc::new)
+        .map(|x| Arc::from(&**x))
         .collect();
 
     let mut amount = 0;
@@ -1027,7 +1020,7 @@ pub(crate) async fn handle_incoming_pdu<'a>(
             if amount > 100 {
                 // Max limit reached
                 warn!("Max prev event limit reached!");
-                graph.insert((*prev_event_id).clone(), HashSet::new());
+                graph.insert((*prev_event_id).to_owned(), HashSet::new());
                 continue;
             }
 
@@ -1038,27 +1031,27 @@ pub(crate) async fn handle_incoming_pdu<'a>(
                     amount += 1;
                     for prev_prev in &pdu.prev_events {
                         if !graph.contains_key(prev_prev) {
-                            todo_outlier_stack.push(dbg!(Arc::new(prev_prev.clone())));
+                            todo_outlier_stack.push(dbg!(Arc::from(&**prev_prev)));
                         }
                     }
 
                     graph.insert(
-                        (*prev_event_id).clone(),
+                        (*prev_event_id).to_owned(),
                         pdu.prev_events.iter().cloned().collect(),
                     );
                 } else {
                     // Time based check failed
-                    graph.insert((*prev_event_id).clone(), HashSet::new());
+                    graph.insert((*prev_event_id).to_owned(), HashSet::new());
                 }
 
                 eventid_info.insert(prev_event_id.clone(), (pdu, json));
             } else {
                 // Get json failed
-                graph.insert((*prev_event_id).clone(), HashSet::new());
+                graph.insert((*prev_event_id).to_owned(), HashSet::new());
             }
         } else {
             // Fetch and handle failed
-            graph.insert((*prev_event_id).clone(), HashSet::new());
+            graph.insert((*prev_event_id).to_owned(), HashSet::new());
         }
     }
 
@@ -1074,7 +1067,6 @@ pub(crate) async fn handle_incoming_pdu<'a>(
                     .get(event_id)
                     .map_or_else(|| uint!(0), |info| info.0.origin_server_ts),
             ),
-            ruma::event_id!("$notimportant"),
         ))
     })
     .map_err(|_| "Error sorting prev events".to_owned())?;
@@ -1084,7 +1076,7 @@ pub(crate) async fn handle_incoming_pdu<'a>(
         if errors >= 5 {
             break;
         }
-        if let Some((pdu, json)) = eventid_info.remove(&prev_id) {
+        if let Some((pdu, json)) = eventid_info.remove(&*prev_id) {
             if pdu.origin_server_ts < first_pdu_in_room.origin_server_ts {
                 continue;
             }
@@ -1200,8 +1192,7 @@ fn handle_outlier_pdu<'a>(
             &incoming_pdu
                 .auth_events
                 .iter()
-                .cloned()
-                .map(Arc::new)
+                .map(|x| Arc::from(&**x))
                 .collect::<Vec<_>>(),
             create_event,
             room_id,
@@ -1331,7 +1322,7 @@ async fn upgrade_outlier_to_timeline_pdu(
     let mut state_at_incoming_event = None;
 
     if incoming_pdu.prev_events.len() == 1 {
-        let prev_event = &incoming_pdu.prev_events[0];
+        let prev_event = &*incoming_pdu.prev_events[0];
         let prev_event_sstatehash = db
             .rooms
             .pdu_shortstatehash(prev_event)
@@ -1353,7 +1344,7 @@ async fn upgrade_outlier_to_timeline_pdu(
                     .get_or_create_shortstatekey(&prev_pdu.kind, state_key, &db.globals)
                     .map_err(|_| "Failed to create shortstatekey.".to_owned())?;
 
-                state.insert(shortstatekey, Arc::new(prev_event.clone()));
+                state.insert(shortstatekey, Arc::from(prev_event));
                 // Now it's the state after the pdu
             }
 
@@ -1397,7 +1388,7 @@ async fn upgrade_outlier_to_timeline_pdu(
                         .rooms
                         .get_or_create_shortstatekey(&prev_event.kind, state_key, &db.globals)
                         .map_err(|_| "Failed to create shortstatekey.".to_owned())?;
-                    leaf_state.insert(shortstatekey, Arc::new(prev_event.event_id.clone()));
+                    leaf_state.insert(shortstatekey, Arc::from(&*prev_event.event_id));
                     // Now it's the state after the pdu
                 }
 
@@ -1410,14 +1401,14 @@ async fn upgrade_outlier_to_timeline_pdu(
                         .get_statekey_from_short(k)
                         .map_err(|_| "Failed to get_statekey_from_short.".to_owned())?;
 
-                    state.insert(k, (*id).clone());
+                    state.insert(k, (*id).to_owned());
                     starting_events.push(id);
                 }
 
                 auth_chain_sets.push(
                     get_auth_chain(room_id, starting_events, db)
                         .map_err(|_| "Failed to load auth chain.".to_owned())?
-                        .map(|event_id| (*event_id).clone())
+                        .map(|event_id| (*event_id).to_owned())
                         .collect(),
                 );
 
@@ -1444,7 +1435,7 @@ async fn upgrade_outlier_to_timeline_pdu(
                                 .rooms
                                 .get_or_create_shortstatekey(&event_type, &state_key, &db.globals)
                                 .map_err(|_| "Failed to get_or_create_shortstatekey".to_owned())?;
-                            Ok((shortstatekey, Arc::new(event_id)))
+                            Ok((shortstatekey, Arc::from(event_id)))
                         })
                         .collect::<Result<_, String>>()?,
                 ),
@@ -1479,8 +1470,7 @@ async fn upgrade_outlier_to_timeline_pdu(
                     origin,
                     &res.pdu_ids
                         .iter()
-                        .cloned()
-                        .map(Arc::new)
+                        .map(|x| Arc::from(&**x))
                         .collect::<Vec<_>>(),
                     create_event,
                     room_id,
@@ -1488,7 +1478,7 @@ async fn upgrade_outlier_to_timeline_pdu(
                 )
                 .await;
 
-                let mut state = BTreeMap::new();
+                let mut state: BTreeMap<_, Arc<EventId>> = BTreeMap::new();
                 for (pdu, _) in state_vec {
                     let state_key = pdu
                         .state_key
@@ -1502,7 +1492,7 @@ async fn upgrade_outlier_to_timeline_pdu(
 
                     match state.entry(shortstatekey) {
                         btree_map::Entry::Vacant(v) => {
-                            v.insert(Arc::new(pdu.event_id.clone()));
+                            v.insert(Arc::from(&*pdu.event_id));
                         }
                         btree_map::Entry::Occupied(_) => return Err(
                             "State event's type and state_key combination exists multiple times."
@@ -1577,7 +1567,7 @@ async fn upgrade_outlier_to_timeline_pdu(
             .roomid_mutex_state
             .write()
             .unwrap()
-            .entry(room_id.clone())
+            .entry(room_id.to_owned())
             .or_default(),
     );
     let state_lock = mutex_state.lock().await;
@@ -1647,7 +1637,7 @@ async fn upgrade_outlier_to_timeline_pdu(
             db,
             &incoming_pdu,
             val,
-            extremities,
+            extremities.iter().map(Deref::deref),
             state_ids_compressed,
             soft_fail,
             &state_lock,
@@ -1715,7 +1705,7 @@ async fn upgrade_outlier_to_timeline_pdu(
                     .rooms
                     .get_or_create_shortstatekey(&leaf_pdu.kind, state_key, &db.globals)
                     .map_err(|_| "Failed to create shortstatekey.".to_owned())?;
-                leaf_state.insert(shortstatekey, Arc::new(leaf_pdu.event_id.clone()));
+                leaf_state.insert(shortstatekey, Arc::from(&*leaf_pdu.event_id));
                 // Now it's the state after the pdu
             }
 
@@ -1730,7 +1720,7 @@ async fn upgrade_outlier_to_timeline_pdu(
                 .get_or_create_shortstatekey(&incoming_pdu.kind, state_key, &db.globals)
                 .map_err(|_| "Failed to create shortstatekey.".to_owned())?;
 
-            state_after.insert(shortstatekey, Arc::new(incoming_pdu.event_id.clone()));
+            state_after.insert(shortstatekey, Arc::from(&*incoming_pdu.event_id));
         }
         fork_states.push(state_after);
 
@@ -1762,7 +1752,7 @@ async fn upgrade_outlier_to_timeline_pdu(
                         db,
                     )
                     .map_err(|_| "Failed to load auth chain.".to_owned())?
-                    .map(|event_id| (*event_id).clone())
+                    .map(|event_id| (*event_id).to_owned())
                     .collect(),
                 );
             }
@@ -1774,7 +1764,7 @@ async fn upgrade_outlier_to_timeline_pdu(
                         .map(|(k, id)| {
                             db.rooms
                                 .get_statekey_from_short(k)
-                                .map(|k| (k, (*id).clone()))
+                                .map(|k| (k, (*id).to_owned()))
                         })
                         .collect::<Result<StateMap<_>>>()
                 })
@@ -1832,7 +1822,7 @@ async fn upgrade_outlier_to_timeline_pdu(
         db,
         &incoming_pdu,
         val,
-        extremities,
+        extremities.iter().map(Deref::deref),
         state_ids_compressed,
         soft_fail,
         &state_lock,
@@ -1874,7 +1864,8 @@ pub(crate) fn fetch_and_handle_outliers<'a>(
 
         let mut pdus = vec![];
         for id in events {
-            if let Some((time, tries)) = db.globals.bad_event_ratelimiter.read().unwrap().get(id) {
+            if let Some((time, tries)) = db.globals.bad_event_ratelimiter.read().unwrap().get(&**id)
+            {
                 // Exponential backoff
                 let mut min_elapsed_duration = Duration::from_secs(5 * 60) * (*tries) * (*tries);
                 if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) {
@@ -1914,7 +1905,7 @@ pub(crate) fn fetch_and_handle_outliers<'a>(
                                 match crate::pdu::gen_event_id_canonical_json(&res.pdu) {
                                     Ok(t) => t,
                                     Err(_) => {
-                                        back_off((**id).clone());
+                                        back_off((**id).to_owned());
                                         continue;
                                     }
                                 };
@@ -1939,14 +1930,14 @@ pub(crate) fn fetch_and_handle_outliers<'a>(
                                 Ok((pdu, json)) => (pdu, Some(json)),
                                 Err(e) => {
                                     warn!("Authentication of event {} failed: {:?}", id, e);
-                                    back_off((**id).clone());
+                                    back_off((**id).to_owned());
                                     continue;
                                 }
                             }
                         }
                         Err(_) => {
                             warn!("Failed to fetch event: {}", id);
-                            back_off((**id).clone());
+                            back_off((**id).to_owned());
                             continue;
                         }
                     }
@@ -2124,11 +2115,11 @@ pub(crate) async fn fetch_signing_keys(
 /// Append the incoming event setting the state snapshot to the state from the
 /// server that sent the event.
 #[tracing::instrument(skip(db, pdu, pdu_json, new_room_leaves, state_ids_compressed, _mutex_lock))]
-fn append_incoming_pdu(
+fn append_incoming_pdu<'a>(
     db: &Database,
     pdu: &PduEvent,
     pdu_json: CanonicalJsonObject,
-    new_room_leaves: HashSet<EventId>,
+    new_room_leaves: impl IntoIterator<Item = &'a EventId> + Clone + Debug,
     state_ids_compressed: HashSet<CompressedStateEvent>,
     soft_fail: bool,
     _mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room mutex
@@ -2145,19 +2136,12 @@ fn append_incoming_pdu(
     if soft_fail {
         db.rooms
             .mark_as_referenced(&pdu.room_id, &pdu.prev_events)?;
-        db.rooms.replace_pdu_leaves(
-            &pdu.room_id,
-            &new_room_leaves.into_iter().collect::<Vec<_>>(),
-        )?;
+        db.rooms
+            .replace_pdu_leaves(&pdu.room_id, new_room_leaves.clone())?;
         return Ok(None);
     }
 
-    let pdu_id = db.rooms.append_pdu(
-        pdu,
-        pdu_json,
-        &new_room_leaves.into_iter().collect::<Vec<_>>(),
-        db,
-    )?;
+    let pdu_id = db.rooms.append_pdu(pdu, pdu_json, new_room_leaves, db)?;
 
     for appservice in db.appservice.all()? {
         if db.rooms.appservice_in_room(&pdu.room_id, &appservice, db)? {
@@ -2298,13 +2282,13 @@ fn get_auth_chain_inner(
     event_id: &EventId,
     db: &Database,
 ) -> Result<HashSet<u64>> {
-    let mut todo = vec![event_id.clone()];
+    let mut todo = vec![event_id.to_owned()];
     let mut found = HashSet::new();
 
     while let Some(event_id) = todo.pop() {
         match db.rooms.get_pdu(&event_id) {
             Ok(Some(pdu)) => {
-                if &pdu.room_id != room_id {
+                if pdu.room_id != room_id {
                     return Err(Error::BadRequest(ErrorKind::Forbidden, "Evil event in db"));
                 }
                 for auth_event in &pdu.auth_events {
@@ -2314,7 +2298,7 @@ fn get_auth_chain_inner(
 
                     if !found.contains(&sauthevent) {
                         found.insert(sauthevent);
-                        todo.push(auth_event.clone());
+                        todo.push(auth_event.to_owned());
                     }
                 }
             }
@@ -2363,10 +2347,10 @@ pub fn get_event_route(
         .and_then(|val| val.as_str())
         .ok_or_else(|| Error::bad_database("Invalid event in database"))?;
 
-    let room_id = RoomId::try_from(room_id_str)
+    let room_id = <&RoomId>::try_from(room_id_str)
         .map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
 
-    if !db.rooms.server_in_room(sender_servername, &room_id)? {
+    if !db.rooms.server_in_room(sender_servername, room_id)? {
         return Err(Error::BadRequest(ErrorKind::NotFound, "Event not found."));
     }
 
@@ -2417,7 +2401,7 @@ pub fn get_missing_events_route(
                 .and_then(|val| val.as_str())
                 .ok_or_else(|| Error::bad_database("Invalid event in database"))?;
 
-            let event_room_id = RoomId::try_from(room_id_str)
+            let event_room_id = <&RoomId>::try_from(room_id_str)
                 .map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
 
             if event_room_id != body.room_id {
@@ -2436,7 +2420,7 @@ pub fn get_missing_events_route(
                 continue;
             }
             queued_events.extend_from_slice(
-                &serde_json::from_value::<Vec<EventId>>(
+                &serde_json::from_value::<Vec<Box<EventId>>>(
                     serde_json::to_value(pdu.get("prev_events").cloned().ok_or_else(|| {
                         Error::bad_database("Event in db has no prev_events field.")
                     })?)
@@ -2485,14 +2469,14 @@ pub fn get_event_authorization_route(
         .and_then(|val| val.as_str())
         .ok_or_else(|| Error::bad_database("Invalid event in database"))?;
 
-    let room_id = RoomId::try_from(room_id_str)
+    let room_id = <&RoomId>::try_from(room_id_str)
         .map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
 
-    if !db.rooms.server_in_room(sender_servername, &room_id)? {
+    if !db.rooms.server_in_room(sender_servername, room_id)? {
         return Err(Error::BadRequest(ErrorKind::NotFound, "Event not found."));
     }
 
-    let auth_chain_ids = get_auth_chain(&room_id, vec![Arc::new(body.event_id.clone())], &db)?;
+    let auth_chain_ids = get_auth_chain(room_id, vec![Arc::from(&*body.event_id)], &db)?;
 
     Ok(get_event_authorization::v1::Response {
         auth_chain: auth_chain_ids
@@ -2550,7 +2534,7 @@ pub fn get_room_state_route(
         })
         .collect();
 
-    let auth_chain_ids = get_auth_chain(&body.room_id, vec![Arc::new(body.event_id.clone())], &db)?;
+    let auth_chain_ids = get_auth_chain(&body.room_id, vec![Arc::from(&*body.event_id)], &db)?;
 
     Ok(get_room_state::v1::Response {
         auth_chain: auth_chain_ids
@@ -2606,13 +2590,13 @@ pub fn get_room_state_ids_route(
         .rooms
         .state_full_ids(shortstatehash)?
         .into_iter()
-        .map(|(_, id)| (*id).clone())
+        .map(|(_, id)| (*id).to_owned())
         .collect();
 
-    let auth_chain_ids = get_auth_chain(&body.room_id, vec![Arc::new(body.event_id.clone())], &db)?;
+    let auth_chain_ids = get_auth_chain(&body.room_id, vec![Arc::from(&*body.event_id)], &db)?;
 
     Ok(get_room_state_ids::v1::Response {
-        auth_chain_ids: auth_chain_ids.map(|id| (*id).clone()).collect(),
+        auth_chain_ids: auth_chain_ids.map(|id| (*id).to_owned()).collect(),
         pdu_ids,
     }
     .into())
@@ -2671,9 +2655,8 @@ pub fn create_join_event_template_route(
     };
 
     // If there was no create event yet, assume we are creating a version 6 room right now
-    let room_version_id = create_event_content.map_or(RoomVersionId::Version6, |create_event| {
-        create_event.room_version
-    });
+    let room_version_id =
+        create_event_content.map_or(RoomVersionId::V6, |create_event| create_event.room_version);
     let room_version = RoomVersion::new(&room_version_id).expect("room version is supported");
 
     if !body.ver.contains(&room_version_id) {
@@ -2726,7 +2709,7 @@ pub fn create_join_event_template_route(
     }
 
     let pdu = PduEvent {
-        event_id: ruma::event_id!("$thiswillbefilledinlater"),
+        event_id: ruma::event_id!("$thiswillbefilledinlater").to_owned(),
         room_id: body.room_id.clone(),
         sender: body.user_id.clone(),
         origin_server_ts: utils::millis_since_unix_epoch()
@@ -2838,7 +2821,7 @@ async fn create_join_event(
             .roomid_mutex_federation
             .write()
             .unwrap()
-            .entry(room_id.clone())
+            .entry(room_id.to_owned())
             .or_default(),
     );
     let mutex_lock = mutex.lock().await;
@@ -2937,8 +2920,7 @@ pub async fn create_invite_route(
         return Err(Error::bad_config("Federation is disabled."));
     }
 
-    if body.room_version != RoomVersionId::Version5 && body.room_version != RoomVersionId::Version6
-    {
+    if body.room_version != RoomVersionId::V5 && body.room_version != RoomVersionId::V6 {
         return Err(Error::BadRequest(
             ErrorKind::IncompatibleRoomVersion {
                 room_version: body.room_version.clone(),
@@ -2959,7 +2941,7 @@ pub async fn create_invite_route(
     .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Failed to sign event."))?;
 
     // Generate event id
-    let event_id = EventId::try_from(&*format!(
+    let event_id = EventId::parse(format!(
         "${}",
         ruma::signatures::reference_hash(&signed_event, &body.room_version)
             .expect("ruma can calculate reference hashes")
@@ -2972,7 +2954,7 @@ pub async fn create_invite_route(
         CanonicalJsonValue::String(event_id.into()),
     );
 
-    let sender = serde_json::from_value(
+    let sender: Box<_> = serde_json::from_value(
         signed_event
             .get("sender")
             .ok_or(Error::BadRequest(
@@ -2984,7 +2966,7 @@ pub async fn create_invite_route(
     )
     .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "sender is not a user id."))?;
 
-    let invited_user = serde_json::from_value(
+    let invited_user: Box<_> = serde_json::from_value(
         signed_event
             .get("state_key")
             .ok_or(Error::BadRequest(
@@ -3235,7 +3217,7 @@ pub(crate) async fn fetch_required_signing_keys(
 
         let fetch_res = fetch_signing_keys(
             db,
-            &Box::<ServerName>::try_from(&**signature_server).map_err(|_| {
+            signature_server.as_str().try_into().map_err(|_| {
                 Error::BadServerResponse("Invalid servername in signatures of server response pdu.")
             })?,
             signature_ids,
@@ -3263,7 +3245,7 @@ pub(crate) async fn fetch_required_signing_keys(
 // the PDUs and either cache the key or add it to the list that needs to be retrieved.
 fn get_server_keys_from_cache(
     pdu: &RawJsonValue,
-    servers: &mut BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, QueryCriteria>>,
+    servers: &mut BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, QueryCriteria>>,
     room_version: &RoomVersionId,
     pub_key_map: &mut RwLockWriteGuard<'_, BTreeMap<String, BTreeMap<String, String>>>,
     db: &Database,
@@ -3273,19 +3255,20 @@ fn get_server_keys_from_cache(
         Error::BadServerResponse("Invalid PDU in server response")
     })?;
 
-    let event_id = EventId::try_from(&*format!(
+    let event_id = format!(
         "${}",
         ruma::signatures::reference_hash(&value, room_version)
             .expect("ruma can calculate reference hashes")
-    ))
-    .expect("ruma's reference hashes are valid event ids");
+    );
+    let event_id = <&EventId>::try_from(event_id.as_str())
+        .expect("ruma's reference hashes are valid event ids");
 
     if let Some((time, tries)) = db
         .globals
         .bad_event_ratelimiter
         .read()
         .unwrap()
-        .get(&event_id)
+        .get(event_id)
     {
         // Exponential backoff
         let mut min_elapsed_duration = Duration::from_secs(30) * (*tries) * (*tries);
@@ -3319,7 +3302,7 @@ fn get_server_keys_from_cache(
         let contains_all_ids =
             |keys: &BTreeMap<String, String>| signature_ids.iter().all(|id| keys.contains_key(id));
 
-        let origin = &Box::<ServerName>::try_from(&**signature_server).map_err(|_| {
+        let origin = <&ServerName>::try_from(signature_server.as_str()).map_err(|_| {
             Error::BadServerResponse("Invalid servername in signatures of server response pdu.")
         })?;
 
@@ -3338,7 +3321,7 @@ fn get_server_keys_from_cache(
 
         if !contains_all_ids(&result) {
             trace!("Signing key not loaded for {}", origin);
-            servers.insert(origin.clone(), BTreeMap::new());
+            servers.insert(origin.to_owned(), BTreeMap::new());
         }
 
         pub_key_map.insert(origin.to_string(), result);
@@ -3353,7 +3336,7 @@ pub(crate) async fn fetch_join_signing_keys(
     pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, String>>>,
     db: &Database,
 ) -> Result<()> {
-    let mut servers: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, QueryCriteria>> =
+    let mut servers: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, QueryCriteria>> =
         BTreeMap::new();
 
     {
@@ -3387,10 +3370,6 @@ pub(crate) async fn fetch_join_signing_keys(
                 server,
                 get_remote_server_keys_batch::v2::Request {
                     server_keys: servers.clone(),
-                    minimum_valid_until_ts: MilliSecondsSinceUnixEpoch::from_system_time(
-                        SystemTime::now() + Duration::from_secs(60),
-                    )
-                    .expect("time is valid"),
                 },
             )
             .await