diff --git a/Cargo.lock b/Cargo.lock
index 35d8926bb39dddaad73661081e50ea2d82a7139e..6448c77d2452b19b1f8b7e74f91f3ab62ec44e4c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5103,7 +5103,7 @@ version = "1.0.0"
 dependencies = [
  "cumulus-primitives-proof-size-hostfunction 0.2.0",
  "cumulus-primitives-storage-weight-reclaim 1.0.0",
- "derivative",
+ "derive-where",
  "docify",
  "frame-benchmarking 28.0.0",
  "frame-support 28.0.0",
@@ -28260,7 +28260,7 @@ version = "7.0.0"
 dependencies = [
  "array-bytes",
  "bounded-collections",
- "derivative",
+ "derive-where",
  "environmental",
  "frame-support 28.0.0",
  "hex",
diff --git a/Cargo.toml b/Cargo.toml
index 36c048d77c8ec0b62e95bf7ac02277df5086738f..0d415fe4fdbd46d86394d73060197e12119b16e6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -740,8 +740,8 @@ cumulus-test-relay-sproof-builder = { path = "cumulus/test/relay-sproof-builder"
 cumulus-test-runtime = { path = "cumulus/test/runtime" }
 cumulus-test-service = { path = "cumulus/test/service" }
 curve25519-dalek = { version = "4.1.3" }
-derivative = { version = "2.2.0", default-features = false }
 derive-syn-parse = { version = "0.2.0" }
+derive-where = { version = "1.2.7" }
 derive_more = { version = "0.99.17", default-features = false }
 digest = { version = "0.10.3", default-features = false }
 directories = { version = "5.0.1" }
diff --git a/cumulus/pallets/weight-reclaim/Cargo.toml b/cumulus/pallets/weight-reclaim/Cargo.toml
index 8bde6abaff6a1a9e53f0e7048d94b18cc43c5325..d412a9b105d989156771a6a0a5fc24e0a3ac59ae 100644
--- a/cumulus/pallets/weight-reclaim/Cargo.toml
+++ b/cumulus/pallets/weight-reclaim/Cargo.toml
@@ -27,7 +27,7 @@ frame-system = { workspace = true }
 
 # Other dependencies
 codec = { features = ["derive"], workspace = true }
-derivative = { features = ["use_core"], workspace = true }
+derive-where = { workspace = true }
 docify = { workspace = true }
 log = { workspace = true, default-features = true }
 scale-info = { features = ["derive"], workspace = true }
diff --git a/cumulus/pallets/weight-reclaim/src/lib.rs b/cumulus/pallets/weight-reclaim/src/lib.rs
index bd9929033af14e43614ea1cd70bdd1b3232a6cfe..7bbd2cf29d831942520dd680eee8ddc9da853b50 100644
--- a/cumulus/pallets/weight-reclaim/src/lib.rs
+++ b/cumulus/pallets/weight-reclaim/src/lib.rs
@@ -29,7 +29,7 @@ extern crate alloc;
 use alloc::vec::Vec;
 use codec::{Decode, Encode};
 use cumulus_primitives_storage_weight_reclaim::get_proof_size;
-use derivative::Derivative;
+use derive_where::derive_where;
 use frame_support::{
 	dispatch::{DispatchInfo, PostDispatchInfo},
 	pallet_prelude::Weight,
@@ -83,13 +83,8 @@ pub mod pallet {
 /// calculates the unused weight using the post information and reclaim the unused weight.
 /// So this extension can be used as a drop-in replacement for `WeightReclaim` extension for
 /// parachains.
-#[derive(Encode, Decode, TypeInfo, Derivative)]
-#[derivative(
-	Clone(bound = "S: Clone"),
-	Eq(bound = "S: Eq"),
-	PartialEq(bound = "S: PartialEq"),
-	Default(bound = "S: Default")
-)]
+#[derive(Encode, Decode, TypeInfo)]
+#[derive_where(Clone, Eq, PartialEq, Default; S)]
 #[scale_info(skip_type_params(T))]
 pub struct StorageWeightReclaim<T, S>(pub S, core::marker::PhantomData<T>);
 
diff --git a/polkadot/xcm/Cargo.toml b/polkadot/xcm/Cargo.toml
index e90354e4e6ac7697df704e495ee08a56c7df587e..f5f824ee409f0b12d05a822f2970d1c92b3c7649 100644
--- a/polkadot/xcm/Cargo.toml
+++ b/polkadot/xcm/Cargo.toml
@@ -15,7 +15,7 @@ workspace = true
 array-bytes = { workspace = true, default-features = true }
 bounded-collections = { features = ["serde"], workspace = true }
 codec = { features = ["derive", "max-encoded-len"], workspace = true }
-derivative = { features = ["use_core"], workspace = true }
+derive-where = { workspace = true }
 environmental = { workspace = true }
 frame-support = { workspace = true }
 hex-literal = { workspace = true, default-features = true }
diff --git a/polkadot/xcm/src/lib.rs b/polkadot/xcm/src/lib.rs
index a41a8e797b0f703302f62be04769c07ad2b9c3c4..2271835a9a5e87b6616e61f42d35ee8775abdb9b 100644
--- a/polkadot/xcm/src/lib.rs
+++ b/polkadot/xcm/src/lib.rs
@@ -25,7 +25,7 @@
 extern crate alloc;
 
 use codec::{Decode, DecodeLimit, Encode, Error as CodecError, Input, MaxEncodedLen};
-use derivative::Derivative;
+use derive_where::derive_where;
 use frame_support::dispatch::GetDispatchInfo;
 use scale_info::TypeInfo;
 
@@ -88,13 +88,7 @@ macro_rules! versioned_type {
 		$(#[$index5:meta])+
 		V5($v5:ty),
 	}) => {
-		#[derive(Derivative, Encode, Decode, TypeInfo)]
-		#[derivative(
-			Clone(bound = ""),
-			Eq(bound = ""),
-			PartialEq(bound = ""),
-			Debug(bound = "")
-		)]
+		#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, TypeInfo)]
 		#[codec(encode_bound())]
 		#[codec(decode_bound())]
 		#[scale_info(replace_segment("staging_xcm", "xcm"))]
@@ -311,8 +305,8 @@ versioned_type! {
 }
 
 /// A single XCM message, together with its version code.
-#[derive(Derivative, Encode, Decode, TypeInfo)]
-#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
+#[derive(Encode, Decode, TypeInfo)]
+#[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
 #[scale_info(bounds(), skip_type_params(RuntimeCall))]
diff --git a/polkadot/xcm/src/v3/mod.rs b/polkadot/xcm/src/v3/mod.rs
index b60209a440c620f52746c407691213b664d215b7..6ae987a9830f1c6e426c1030316b97ecf6611262 100644
--- a/polkadot/xcm/src/v3/mod.rs
+++ b/polkadot/xcm/src/v3/mod.rs
@@ -28,7 +28,7 @@ use codec::{
 	MaxEncodedLen,
 };
 use core::{fmt::Debug, result};
-use derivative::Derivative;
+use derive_where::derive_where;
 use scale_info::TypeInfo;
 
 mod junction;
@@ -57,8 +57,8 @@ pub const VERSION: super::Version = 3;
 /// An identifier for a query.
 pub type QueryId = u64;
 
-#[derive(Derivative, Default, Encode, TypeInfo)]
-#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
+#[derive(Default, Encode, TypeInfo)]
+#[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[scale_info(bounds(), skip_type_params(Call))]
 #[scale_info(replace_segment("staging_xcm", "xcm"))]
@@ -474,15 +474,8 @@ impl XcmContext {
 ///
 /// This is the inner XCM format and is version-sensitive. Messages are typically passed using the
 /// outer XCM format, known as `VersionedXcm`.
-#[derive(
-	Derivative,
-	Encode,
-	Decode,
-	TypeInfo,
-	xcm_procedural::XcmWeightInfoTrait,
-	xcm_procedural::Builder,
-)]
-#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
+#[derive(Encode, Decode, TypeInfo, xcm_procedural::XcmWeightInfoTrait, xcm_procedural::Builder)]
+#[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
 #[scale_info(bounds(), skip_type_params(Call))]
diff --git a/polkadot/xcm/src/v4/mod.rs b/polkadot/xcm/src/v4/mod.rs
index a0ce551b7608cd2ff751eeb10877ef764cbde38f..66816e2fb6e7e3e4aaee7cef5de32d647c679d66 100644
--- a/polkadot/xcm/src/v4/mod.rs
+++ b/polkadot/xcm/src/v4/mod.rs
@@ -35,7 +35,7 @@ use codec::{
 	MaxEncodedLen,
 };
 use core::{fmt::Debug, result};
-use derivative::Derivative;
+use derive_where::derive_where;
 use frame_support::dispatch::GetDispatchInfo;
 use scale_info::TypeInfo;
 
@@ -65,8 +65,8 @@ pub const VERSION: super::Version = 4;
 /// An identifier for a query.
 pub type QueryId = u64;
 
-#[derive(Derivative, Default, Encode, TypeInfo)]
-#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
+#[derive(Default, Encode, TypeInfo)]
+#[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
 #[scale_info(bounds(), skip_type_params(Call))]
@@ -436,15 +436,8 @@ impl XcmContext {
 ///
 /// This is the inner XCM format and is version-sensitive. Messages are typically passed using the
 /// outer XCM format, known as `VersionedXcm`.
-#[derive(
-	Derivative,
-	Encode,
-	Decode,
-	TypeInfo,
-	xcm_procedural::XcmWeightInfoTrait,
-	xcm_procedural::Builder,
-)]
-#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
+#[derive(Encode, Decode, TypeInfo, xcm_procedural::XcmWeightInfoTrait, xcm_procedural::Builder)]
+#[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
 #[scale_info(bounds(), skip_type_params(Call))]
diff --git a/polkadot/xcm/src/v5/mod.rs b/polkadot/xcm/src/v5/mod.rs
index 21845d07529efda1b0843ce77a26108eb43a92d6..51f6d839e972abfc3b98e94c7e649f7f2b9426bb 100644
--- a/polkadot/xcm/src/v5/mod.rs
+++ b/polkadot/xcm/src/v5/mod.rs
@@ -29,7 +29,7 @@ use codec::{
 	MaxEncodedLen,
 };
 use core::{fmt::Debug, result};
-use derivative::Derivative;
+use derive_where::derive_where;
 use scale_info::TypeInfo;
 
 mod asset;
@@ -59,8 +59,8 @@ pub const VERSION: super::Version = 5;
 /// An identifier for a query.
 pub type QueryId = u64;
 
-#[derive(Derivative, Default, Encode, TypeInfo)]
-#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
+#[derive(Default, Encode, TypeInfo)]
+#[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
 #[scale_info(bounds(), skip_type_params(Call))]
@@ -378,15 +378,8 @@ impl XcmContext {
 ///
 /// This is the inner XCM format and is version-sensitive. Messages are typically passed using the
 /// outer XCM format, known as `VersionedXcm`.
-#[derive(
-	Derivative,
-	Encode,
-	Decode,
-	TypeInfo,
-	xcm_procedural::XcmWeightInfoTrait,
-	xcm_procedural::Builder,
-)]
-#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
+#[derive(Encode, Decode, TypeInfo, xcm_procedural::XcmWeightInfoTrait, xcm_procedural::Builder)]
+#[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
 #[scale_info(bounds(), skip_type_params(Call))]
diff --git a/prdoc/pr_7324.prdoc b/prdoc/pr_7324.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..e4fb7db781766656a6d02cf0d9bd7b7fd16bce8c
--- /dev/null
+++ b/prdoc/pr_7324.prdoc
@@ -0,0 +1,17 @@
+title: Replace derivative dependency with derive-where
+author: conr2d
+topic: runtime
+
+doc:
+- audience: Runtime Dev
+  description: |-
+    The `derivative` crate, previously used to derive basic traits for structs with
+    generics or enums, is no longer actively maintained. It has been replaced with
+    the `derive-where` crate, which offers a more straightforward syntax while
+    providing the same features as `derivative`.
+
+crates:
+  - name: cumulus-pallet-weight-reclaim
+    bump: patch
+  - name: staging-xcm
+    bump: patch