diff --git a/include/mtx/identifiers.hpp b/include/mtx/identifiers.hpp
index b80b722b0384bedfdfd588f16157b45596aedcf8..e6ead11f3ca2478e08a2b3a866cecd80c1f55645 100644
--- a/include/mtx/identifiers.hpp
+++ b/include/mtx/identifiers.hpp
@@ -9,6 +9,7 @@
 #include <nlohmann/json.hpp>
 #endif
 
+#include <compare>
 #include <stdexcept>
 
 namespace mtx {
@@ -21,11 +22,11 @@ class ID
 {
 public:
     //! Returns the unique local part of the identifier.
-    std::string localpart() const { return localpart_; }
+    [[nodiscard]] std::string localpart() const { return localpart_; }
     //! Returns the name of the originating homeserver.
-    std::string hostname() const { return hostname_; }
+    [[nodiscard]] std::string hostname() const { return hostname_; }
     //! Returns the whole identifier (localpart + hostname).
-    std::string to_string() const { return id_; }
+    [[nodiscard]] std::string to_string() const { return id_; }
 
 protected:
     //! Local part of the identifier.
@@ -45,7 +46,7 @@ public:
 
 private:
     //! The `sigil` used to represent an Event.
-    std::string sigil = "$";
+    static constexpr std::string_view sigil = "$";
 
     friend void from_json(const nlohmann::json &obj, Event &event);
     friend void to_json(nlohmann::json &obj, const Event &event);
@@ -59,7 +60,7 @@ public:
     friend Identifier parse(const std::string &id);
 
 private:
-    std::string sigil = "!";
+    static constexpr std::string_view sigil = "!";
 
     friend void from_json(const nlohmann::json &obj, Room &room);
     friend void to_json(nlohmann::json &obj, const Room &room);
@@ -71,10 +72,11 @@ class User : public ID
 public:
     template<typename Identifier>
     friend Identifier parse(const std::string &id);
-    friend bool operator<(const User &a, const User &b) { return a.id_ < b.id_; }
+    constexpr auto operator<=>(User const &other) const noexcept { return id_ <=> other.id_; };
+    constexpr bool operator==(User const &other) const noexcept { return id_ == other.id_; };
 
 private:
-    std::string sigil = "@";
+    static constexpr std::string_view sigil = "@";
 
     friend void from_json(const nlohmann::json &obj, User &user);
     friend void to_json(nlohmann::json &obj, const User &user);
@@ -88,35 +90,35 @@ template<typename Identifier>
 Identifier
 parse(const std::string &id)
 {
-    Identifier identifier;
-
     if (id.empty()) {
         // FIXME: enable logging only in debug mode.
         /* std::cout << "mtx::identifiers - Empty matrix identifier was given" << std::endl;
          */
-        return identifier;
+        return {};
     }
 
-    if (std::string(1, id.at(0)) != identifier.sigil)
-        throw std::invalid_argument(std::string(id + ": missing sigil " + identifier.sigil));
+    if (std::string(1, id.at(0)) != Identifier::sigil)
+        throw std::invalid_argument(id + ": missing sigil " + std::string(Identifier::sigil));
 
     const auto parts = id.find_first_of(':');
 
     // Split into localpart and server.
     if (parts != std::string::npos) {
+        Identifier identifier{};
         identifier.localpart_ = id.substr(1, parts - 1);
         identifier.hostname_  = id.substr(parts + 1);
         identifier.id_        = id;
-    } else if (identifier.sigil == "$") {
+        return identifier;
+    } else if (Identifier::sigil == "$") {
         // V3 event ids don't use ':' at all, don't parse them the same way.
+        Identifier identifier{};
         identifier.localpart_ = id;
         identifier.hostname_  = id;
         identifier.id_        = id;
+        return identifier;
     } else {
-        throw std::invalid_argument(std::string(id + ": invalid id"));
+        throw std::invalid_argument(id + ": invalid id");
     }
-
-    return identifier;
 }
 
 } // namespace identifiers
diff --git a/lib/structs/responses/sync.cpp b/lib/structs/responses/sync.cpp
index 9a0b4e196b394ca15b0027a6b25f3ada4101db79..a37cf2f9099d6ae4270d0614db14962d4016ae0e 100644
--- a/lib/structs/responses/sync.cpp
+++ b/lib/structs/responses/sync.cpp
@@ -214,8 +214,7 @@ from_json(const json &obj, DeviceLists &device_lists)
 
         std::erase_if(device_lists.left, [](const std::string &user) {
             if (user.size() > 255) {
-                mtx::utils::log::log()->warn(
-                        "Invalid userid in device list left.");
+                mtx::utils::log::log()->warn("Invalid userid in device list left.");
                 return true;
             } else
                 return false;