diff --git a/polkadot/runtime/westend/Cargo.toml b/polkadot/runtime/westend/Cargo.toml
index 4180828bcfb14d497d9da06bc74da91fa53f8d5f..fcead1dd0b532b17bde7d048fad10cf5f7758d89 100644
--- a/polkadot/runtime/westend/Cargo.toml
+++ b/polkadot/runtime/westend/Cargo.toml
@@ -45,7 +45,7 @@ sp-npos-elections = { path = "../../../substrate/primitives/npos-elections", def
 
 frame-election-provider-support = { path = "../../../substrate/frame/election-provider-support", default-features = false }
 frame-executive = { path = "../../../substrate/frame/executive", default-features = false }
-frame-support = { path = "../../../substrate/frame/support", default-features = false, features = ["tuples-96"] }
+frame-support = { path = "../../../substrate/frame/support", default-features = false, features = ["experimental", "tuples-96"] }
 frame-system = { path = "../../../substrate/frame/system", default-features = false }
 frame-system-rpc-runtime-api = { path = "../../../substrate/frame/system/rpc/runtime-api", default-features = false }
 westend-runtime-constants = { package = "westend-runtime-constants", path = "constants", default-features = false }
diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs
index f1d8841989c4db0f034d52e04915869e1a903d46..62821cae7e49aebc0ed2f186278833500e375ec2 100644
--- a/polkadot/runtime/westend/src/lib.rs
+++ b/polkadot/runtime/westend/src/lib.rs
@@ -17,7 +17,7 @@
 //! The Westend runtime. This can be compiled with `#[no_std]`, ready for Wasm.
 
 #![cfg_attr(not(feature = "std"), no_std)]
-// `construct_runtime!` does a lot of recursion and requires us to increase the limit.
+// `#[frame_support::runtime]!` does a lot of recursion and requires us to increase the limit.
 #![recursion_limit = "512"]
 
 use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
@@ -27,7 +27,7 @@ use beefy_primitives::{
 };
 use frame_election_provider_support::{bounds::ElectionBoundsBuilder, onchain, SequentialPhragmen};
 use frame_support::{
-	construct_runtime, derive_impl,
+	derive_impl,
 	genesis_builder_helper::{build_config, create_default_config},
 	parameter_types,
 	traits::{
@@ -1414,128 +1414,201 @@ impl pallet_asset_rate::Config for Runtime {
 	type BenchmarkHelper = runtime_common::impls::benchmarks::AssetRateArguments;
 }
 
-construct_runtime! {
-	pub enum Runtime
-	{
-		// Basic stuff; balances is uncallable initially.
-		System: frame_system = 0,
-
-		// Babe must be before session.
-		Babe: pallet_babe = 1,
-
-		Timestamp: pallet_timestamp = 2,
-		Indices: pallet_indices = 3,
-		Balances: pallet_balances = 4,
-		TransactionPayment: pallet_transaction_payment = 26,
-
-		// Consensus support.
-		// Authorship must be before session in order to note author in the correct session and era.
-		Authorship: pallet_authorship = 5,
-		Staking: pallet_staking = 6,
-		Offences: pallet_offences = 7,
-		Historical: session_historical = 27,
-
-		Session: pallet_session = 8,
-		Grandpa: pallet_grandpa = 10,
-		AuthorityDiscovery: pallet_authority_discovery = 12,
-
-		// Utility module.
-		Utility: pallet_utility = 16,
-
-		// Less simple identity module.
-		Identity: pallet_identity = 17,
-
-		// Social recovery module.
-		Recovery: pallet_recovery = 18,
-
-		// Vesting. Usable initially, but removed once all vesting is finished.
-		Vesting: pallet_vesting = 19,
-
-		// System scheduler.
-		Scheduler: pallet_scheduler = 20,
-
-		// Preimage registrar.
-		Preimage: pallet_preimage = 28,
-
-		// Sudo.
-		Sudo: pallet_sudo = 21,
-
-		// Proxy module. Late addition.
-		Proxy: pallet_proxy = 22,
-
-		// Multisig module. Late addition.
-		Multisig: pallet_multisig = 23,
-
-		// Election pallet. Only works with staking, but placed here to maintain indices.
-		ElectionProviderMultiPhase: pallet_election_provider_multi_phase = 24,
-
-		// Provides a semi-sorted list of nominators for staking.
-		VoterList: pallet_bags_list::<Instance1> = 25,
-
-		// Nomination pools for staking.
-		NominationPools: pallet_nomination_pools = 29,
-
-		// Fast unstake pallet: extension to staking.
-		FastUnstake: pallet_fast_unstake = 30,
-
-		// OpenGov
-		ConvictionVoting: pallet_conviction_voting = 31,
-		Referenda: pallet_referenda = 32,
-		Origins: pallet_custom_origins = 35,
-		Whitelist: pallet_whitelist = 36,
-
-		// Treasury
-		Treasury: pallet_treasury = 37,
-
-		// Parachains pallets. Start indices at 40 to leave room.
-		ParachainsOrigin: parachains_origin = 41,
-		Configuration: parachains_configuration = 42,
-		ParasShared: parachains_shared = 43,
-		ParaInclusion: parachains_inclusion = 44,
-		ParaInherent: parachains_paras_inherent = 45,
-		ParaScheduler: parachains_scheduler = 46,
-		Paras: parachains_paras = 47,
-		Initializer: parachains_initializer = 48,
-		Dmp: parachains_dmp = 49,
-		// RIP Ump 50
-		Hrmp: parachains_hrmp = 51,
-		ParaSessionInfo: parachains_session_info = 52,
-		ParasDisputes: parachains_disputes = 53,
-		ParasSlashing: parachains_slashing = 54,
-		OnDemandAssignmentProvider: parachains_assigner_on_demand = 56,
-		CoretimeAssignmentProvider: parachains_assigner_coretime = 57,
-
-		// Parachain Onboarding Pallets. Start indices at 60 to leave room.
-		Registrar: paras_registrar = 60,
-		Slots: slots = 61,
-		ParasSudoWrapper: paras_sudo_wrapper = 62,
-		Auctions: auctions = 63,
-		Crowdloan: crowdloan = 64,
-		AssignedSlots: assigned_slots = 65,
-		Coretime: coretime = 66,
-
-		// Pallet for sending XCM.
-		XcmPallet: pallet_xcm = 99,
-
-		// Generalized message queue
-		MessageQueue: pallet_message_queue = 100,
-
-		// Asset rate.
-		AssetRate: pallet_asset_rate = 101,
-
-		// Root testing pallet.
-		RootTesting: pallet_root_testing = 102,
-
-		// BEEFY Bridges support.
-		Beefy: pallet_beefy = 200,
-		// MMR leaf construction must be after session in order to have a leaf's next_auth_set
-		// refer to block<N>. See issue polkadot-fellows/runtimes#160 for details.
-		Mmr: pallet_mmr = 201,
-		BeefyMmrLeaf: pallet_beefy_mmr = 202,
-
-		// Pallet for migrating Identity to a parachain. To be removed post-migration.
-		IdentityMigrator: identity_migrator = 248,
-	}
+#[frame_support::runtime(legacy_ordering)]
+mod runtime {
+	#[runtime::runtime]
+	#[runtime::derive(
+		RuntimeCall,
+		RuntimeEvent,
+		RuntimeError,
+		RuntimeOrigin,
+		RuntimeFreezeReason,
+		RuntimeHoldReason,
+		RuntimeSlashReason,
+		RuntimeLockId,
+		RuntimeTask
+	)]
+	pub struct Runtime;
+
+	// Basic stuff; balances is uncallable initially.
+	#[runtime::pallet_index(0)]
+	pub type System = frame_system;
+
+	// Babe must be before session.
+	#[runtime::pallet_index(1)]
+	pub type Babe = pallet_babe;
+
+	#[runtime::pallet_index(2)]
+	pub type Timestamp = pallet_timestamp;
+	#[runtime::pallet_index(3)]
+	pub type Indices = pallet_indices;
+	#[runtime::pallet_index(4)]
+	pub type Balances = pallet_balances;
+	#[runtime::pallet_index(26)]
+	pub type TransactionPayment = pallet_transaction_payment;
+
+	// Consensus support.
+	// Authorship must be before session in order to note author in the correct session and era.
+	#[runtime::pallet_index(5)]
+	pub type Authorship = pallet_authorship;
+	#[runtime::pallet_index(6)]
+	pub type Staking = pallet_staking;
+	#[runtime::pallet_index(7)]
+	pub type Offences = pallet_offences;
+	#[runtime::pallet_index(27)]
+	pub type Historical = session_historical;
+
+	#[runtime::pallet_index(8)]
+	pub type Session = pallet_session;
+	#[runtime::pallet_index(10)]
+	pub type Grandpa = pallet_grandpa;
+	#[runtime::pallet_index(12)]
+	pub type AuthorityDiscovery = pallet_authority_discovery;
+
+	// Utility module.
+	#[runtime::pallet_index(16)]
+	pub type Utility = pallet_utility;
+
+	// Less simple identity module.
+	#[runtime::pallet_index(17)]
+	pub type Identity = pallet_identity;
+
+	// Social recovery module.
+	#[runtime::pallet_index(18)]
+	pub type Recovery = pallet_recovery;
+
+	// Vesting. Usable initially, but removed once all vesting is finished.
+	#[runtime::pallet_index(19)]
+	pub type Vesting = pallet_vesting;
+
+	// System scheduler.
+	#[runtime::pallet_index(20)]
+	pub type Scheduler = pallet_scheduler;
+
+	// Preimage registrar.
+	#[runtime::pallet_index(28)]
+	pub type Preimage = pallet_preimage;
+
+	// Sudo.
+	#[runtime::pallet_index(21)]
+	pub type Sudo = pallet_sudo;
+
+	// Proxy module. Late addition.
+	#[runtime::pallet_index(22)]
+	pub type Proxy = pallet_proxy;
+
+	// Multisig module. Late addition.
+	#[runtime::pallet_index(23)]
+	pub type Multisig = pallet_multisig;
+
+	// Election pallet. Only works with staking, but placed here to maintain indices.
+	#[runtime::pallet_index(24)]
+	pub type ElectionProviderMultiPhase = pallet_election_provider_multi_phase;
+
+	// Provides a semi-sorted list of nominators for staking.
+	#[runtime::pallet_index(25)]
+	pub type VoterList = pallet_bags_list<Instance1>;
+
+	// Nomination pools for staking.
+	#[runtime::pallet_index(29)]
+	pub type NominationPools = pallet_nomination_pools;
+
+	// Fast unstake pallet = extension to staking.
+	#[runtime::pallet_index(30)]
+	pub type FastUnstake = pallet_fast_unstake;
+
+	// OpenGov
+	#[runtime::pallet_index(31)]
+	pub type ConvictionVoting = pallet_conviction_voting;
+	#[runtime::pallet_index(32)]
+	pub type Referenda = pallet_referenda;
+	#[runtime::pallet_index(35)]
+	pub type Origins = pallet_custom_origins;
+	#[runtime::pallet_index(36)]
+	pub type Whitelist = pallet_whitelist;
+
+	// Treasury
+	#[runtime::pallet_index(37)]
+	pub type Treasury = pallet_treasury;
+
+	// Parachains pallets. Start indices at 40 to leave room.
+	#[runtime::pallet_index(41)]
+	pub type ParachainsOrigin = parachains_origin;
+	#[runtime::pallet_index(42)]
+	pub type Configuration = parachains_configuration;
+	#[runtime::pallet_index(43)]
+	pub type ParasShared = parachains_shared;
+	#[runtime::pallet_index(44)]
+	pub type ParaInclusion = parachains_inclusion;
+	#[runtime::pallet_index(45)]
+	pub type ParaInherent = parachains_paras_inherent;
+	#[runtime::pallet_index(46)]
+	pub type ParaScheduler = parachains_scheduler;
+	#[runtime::pallet_index(47)]
+	pub type Paras = parachains_paras;
+	#[runtime::pallet_index(48)]
+	pub type Initializer = parachains_initializer;
+	#[runtime::pallet_index(49)]
+	pub type Dmp = parachains_dmp;
+	// RIP Ump 50
+	#[runtime::pallet_index(51)]
+	pub type Hrmp = parachains_hrmp;
+	#[runtime::pallet_index(52)]
+	pub type ParaSessionInfo = parachains_session_info;
+	#[runtime::pallet_index(53)]
+	pub type ParasDisputes = parachains_disputes;
+	#[runtime::pallet_index(54)]
+	pub type ParasSlashing = parachains_slashing;
+	#[runtime::pallet_index(56)]
+	pub type OnDemandAssignmentProvider = parachains_assigner_on_demand;
+	#[runtime::pallet_index(57)]
+	pub type CoretimeAssignmentProvider = parachains_assigner_coretime;
+
+	// Parachain Onboarding Pallets. Start indices at 60 to leave room.
+	#[runtime::pallet_index(60)]
+	pub type Registrar = paras_registrar;
+	#[runtime::pallet_index(61)]
+	pub type Slots = slots;
+	#[runtime::pallet_index(62)]
+	pub type ParasSudoWrapper = paras_sudo_wrapper;
+	#[runtime::pallet_index(63)]
+	pub type Auctions = auctions;
+	#[runtime::pallet_index(64)]
+	pub type Crowdloan = crowdloan;
+	#[runtime::pallet_index(65)]
+	pub type AssignedSlots = assigned_slots;
+	#[runtime::pallet_index(66)]
+	pub type Coretime = coretime;
+
+	// Pallet for sending XCM.
+	#[runtime::pallet_index(99)]
+	pub type XcmPallet = pallet_xcm;
+
+	// Generalized message queue
+	#[runtime::pallet_index(100)]
+	pub type MessageQueue = pallet_message_queue;
+
+	// Asset rate.
+	#[runtime::pallet_index(101)]
+	pub type AssetRate = pallet_asset_rate;
+
+	// Root testing pallet.
+	#[runtime::pallet_index(102)]
+	pub type RootTesting = pallet_root_testing;
+
+	// BEEFY Bridges support.
+	#[runtime::pallet_index(200)]
+	pub type Beefy = pallet_beefy;
+	// MMR leaf construction must be after session in order to have a leaf's next_auth_set
+	// refer to block<N>. See issue polkadot-fellows/runtimes#160 for details.
+	#[runtime::pallet_index(201)]
+	pub type Mmr = pallet_mmr;
+	#[runtime::pallet_index(202)]
+	pub type BeefyMmrLeaf = pallet_beefy_mmr;
+
+	// Pallet for migrating Identity to a parachain. To be removed post-migration.
+	#[runtime::pallet_index(248)]
+	pub type IdentityMigrator = identity_migrator;
 }
 
 /// The address format for describing accounts.
diff --git a/prdoc/pr_3754.prdoc b/prdoc/pr_3754.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..94ea6d566088309cbad05d5eed3f248af716c3bc
--- /dev/null
+++ b/prdoc/pr_3754.prdoc
@@ -0,0 +1,13 @@
+# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
+# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
+
+title: Migrates Westend to Runtime V2
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      This PR migrates Westend from `construct_runtime` to Runtime V2 
+      as introduced in https://github.com/paritytech/polkadot-sdk/pull/1378
+
+crates:
+  - name: westend-runtime