diff --git a/polkadot/runtime/parachains/src/coretime/migration.rs b/polkadot/runtime/parachains/src/coretime/migration.rs
index 72eda1ea3f3cd03a50c595a4b36b6188cca81aaa..4f52fc99ec308a7f3dc21aa37495dbbfe8b9464b 100644
--- a/polkadot/runtime/parachains/src/coretime/migration.rs
+++ b/polkadot/runtime/parachains/src/coretime/migration.rs
@@ -222,7 +222,7 @@ mod v_coretime {
 				mask: CoreMask::complete(),
 				assignment: CoreAssignment::Task(p.into()),
 			}]);
-			mk_coretime_call(crate::coretime::CoretimeCalls::Reserve(schedule))
+			mk_coretime_call::<T>(crate::coretime::CoretimeCalls::Reserve(schedule))
 		});
 
 		let leases = lease_holding.into_iter().filter_map(|p| {
@@ -243,14 +243,14 @@ mod v_coretime {
 			let round_up = if valid_until % TIME_SLICE_PERIOD > 0 { 1 } else { 0 };
 			let time_slice = valid_until / TIME_SLICE_PERIOD + TIME_SLICE_PERIOD * round_up;
 			log::trace!(target: "coretime-migration", "Sending of lease holding para {:?}, valid_until: {:?}, time_slice: {:?}", p, valid_until, time_slice);
-			Some(mk_coretime_call(crate::coretime::CoretimeCalls::SetLease(p.into(), time_slice)))
+			Some(mk_coretime_call::<T>(crate::coretime::CoretimeCalls::SetLease(p.into(), time_slice)))
 		});
 
 		let core_count: u16 = configuration::ActiveConfig::<T>::get()
 			.scheduler_params
 			.num_cores
 			.saturated_into();
-		let set_core_count = iter::once(mk_coretime_call(
+		let set_core_count = iter::once(mk_coretime_call::<T>(
 			crate::coretime::CoretimeCalls::NotifyCoreCount(core_count),
 		));
 
@@ -261,7 +261,7 @@ mod v_coretime {
 			}]);
 			// Reserved cores will come before lease cores, so cores will change their assignments
 			// when coretime chain sends us their assign_core calls -> Good test.
-			mk_coretime_call(crate::coretime::CoretimeCalls::Reserve(schedule))
+			mk_coretime_call::<T>(crate::coretime::CoretimeCalls::Reserve(schedule))
 		});
 
 		let message_content = iter::once(Instruction::UnpaidExecution {
diff --git a/polkadot/runtime/parachains/src/coretime/mod.rs b/polkadot/runtime/parachains/src/coretime/mod.rs
index 9095cd90ae0cfea6a72fde2d4730cad28cf97d29..a30f7336f692f28d43b17f1ab6aef5fcdf7f2e96 100644
--- a/polkadot/runtime/parachains/src/coretime/mod.rs
+++ b/polkadot/runtime/parachains/src/coretime/mod.rs
@@ -110,6 +110,11 @@ pub mod pallet {
 		/// Something that provides the weight of this pallet.
 		type WeightInfo: WeightInfo;
 		type SendXcm: SendXcm;
+
+		/// Maximum weight for any XCM transact call that should be executed on the coretime chain.
+		///
+		/// Basically should be `max_weight(set_leases, reserve, notify_core_count)`.
+		type MaxXcmTransactWeight: Get<Weight>;
 	}
 
 	#[pallet::event]
@@ -225,7 +230,7 @@ impl<T: Config> Pallet<T> {
 					weight_limit: WeightLimit::Unlimited,
 					check_origin: None,
 				},
-				mk_coretime_call(crate::coretime::CoretimeCalls::NotifyCoreCount(core_count)),
+				mk_coretime_call::<T>(crate::coretime::CoretimeCalls::NotifyCoreCount(core_count)),
 			]);
 			if let Err(err) = send_xcm::<T::SendXcm>(
 				Location::new(0, [Junction::Parachain(T::BrokerId::get())]),
@@ -244,7 +249,7 @@ impl<T: Config> Pallet<T> {
 				weight_limit: WeightLimit::Unlimited,
 				check_origin: None,
 			},
-			mk_coretime_call(crate::coretime::CoretimeCalls::SwapLeases(one, other)),
+			mk_coretime_call::<T>(crate::coretime::CoretimeCalls::SwapLeases(one, other)),
 		]);
 		if let Err(err) = send_xcm::<T::SendXcm>(
 			Location::new(0, [Junction::Parachain(T::BrokerId::get())]),
@@ -261,12 +266,10 @@ impl<T: Config> OnNewSession<BlockNumberFor<T>> for Pallet<T> {
 	}
 }
 
-fn mk_coretime_call(call: crate::coretime::CoretimeCalls) -> Instruction<()> {
+fn mk_coretime_call<T: Config>(call: crate::coretime::CoretimeCalls) -> Instruction<()> {
 	Instruction::Transact {
 		origin_kind: OriginKind::Superuser,
-		// Largest call is set_lease with 1526 byte:
-		// Longest call is reserve() with 31_000_000
-		require_weight_at_most: Weight::from_parts(170_000_000, 20_000),
+		require_weight_at_most: T::MaxXcmTransactWeight::get(),
 		call: BrokerRuntimePallets::Broker(call).encode().into(),
 	}
 }
diff --git a/polkadot/runtime/parachains/src/mock.rs b/polkadot/runtime/parachains/src/mock.rs
index c91f5be127cd4be06c5ca7f255804328bab7def7..97a75d47ff775401ec549c1fcfd7a247664449fb 100644
--- a/polkadot/runtime/parachains/src/mock.rs
+++ b/polkadot/runtime/parachains/src/mock.rs
@@ -387,6 +387,7 @@ impl assigner_coretime::Config for Test {}
 
 parameter_types! {
 	pub const BrokerId: u32 = 10u32;
+	pub MaxXcmTransactWeight: Weight = Weight::from_parts(10_000_000, 10_000);
 }
 
 impl coretime::Config for Test {
@@ -396,6 +397,7 @@ impl coretime::Config for Test {
 	type BrokerId = BrokerId;
 	type WeightInfo = crate::coretime::TestWeightInfo;
 	type SendXcm = DummyXcmSender;
+	type MaxXcmTransactWeight = MaxXcmTransactWeight;
 }
 
 pub struct DummyXcmSender;
diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs
index ba80fa6942c7791e9166281f0bdf2199a41cf10f..1cfe9adfe13d1c315402c95ff89b86404546a1ce 100644
--- a/polkadot/runtime/rococo/src/lib.rs
+++ b/polkadot/runtime/rococo/src/lib.rs
@@ -1057,6 +1057,7 @@ impl parachains_scheduler::Config for Runtime {
 
 parameter_types! {
 	pub const BrokerId: u32 = BROKER_ID;
+	pub MaxXcmTransactWeight: Weight = Weight::from_parts(200_000_000, 20_000);
 }
 
 impl coretime::Config for Runtime {
@@ -1066,6 +1067,7 @@ impl coretime::Config for Runtime {
 	type BrokerId = BrokerId;
 	type WeightInfo = weights::runtime_parachains_coretime::WeightInfo<Runtime>;
 	type SendXcm = crate::xcm_config::XcmRouter;
+	type MaxXcmTransactWeight = MaxXcmTransactWeight;
 }
 
 parameter_types! {
diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs
index 02933efff944c8a8d60cf11c25e3ca08bb3d1d8d..7924939c79bdf97127685c7bcb0d9f2004267b9e 100644
--- a/polkadot/runtime/westend/src/lib.rs
+++ b/polkadot/runtime/westend/src/lib.rs
@@ -1188,6 +1188,7 @@ impl parachains_scheduler::Config for Runtime {
 
 parameter_types! {
 	pub const BrokerId: u32 = BROKER_ID;
+	pub MaxXcmTransactWeight: Weight = Weight::from_parts(200_000_000, 20_000);
 }
 
 impl coretime::Config for Runtime {
@@ -1197,6 +1198,7 @@ impl coretime::Config for Runtime {
 	type BrokerId = BrokerId;
 	type WeightInfo = weights::runtime_parachains_coretime::WeightInfo<Runtime>;
 	type SendXcm = crate::xcm_config::XcmRouter;
+	type MaxXcmTransactWeight = MaxXcmTransactWeight;
 }
 
 parameter_types! {
diff --git a/prdoc/pr_4189.prdoc b/prdoc/pr_4189.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..74ed7c67cbdeaf17bcc18476e6e011d62e0d8583
--- /dev/null
+++ b/prdoc/pr_4189.prdoc
@@ -0,0 +1,16 @@
+title: "polkadot_runtime_parachains::coretime: Expose `MaxXcmTransactWeight`"
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      Expose `MaxXcmTransactWeight` via the `Config` trait. This exposes the
+      possibility for runtime implementors to set the maximum weight required
+      for the calls on the coretime chain. Basically it needs to be set to
+      `max_weight(set_leases, reserve, notify_core_count)` where `set_leases`
+      etc are the calls on the coretime chain. This ensures that these XCM
+      transact calls send by the relay chain coretime pallet to the coretime
+      chain can be dispatched.
+
+crates:
+  - name: polkadot-runtime-parachains
+    bump: major