diff --git a/prdoc/pr_4912.prdoc b/prdoc/pr_4912.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..dd96054b81fa3853d695b4baa4c9474ec4ea8338
--- /dev/null
+++ b/prdoc/pr_4912.prdoc
@@ -0,0 +1,15 @@
+# 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: Removed `pallet::getter` usage from the pallet-babe
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      This PR removed `pallet::getter`s from `pallet-babe`s storage items.
+      When accessed inside the pallet, use the syntax `StorageItem::<T>::get()`.
+      When accessed outside the pallet, use the public functions of storage.
+
+crates:
+  - name: pallet-babe
+    bump: minor
diff --git a/substrate/frame/babe/src/lib.rs b/substrate/frame/babe/src/lib.rs
index 686ba6ec2d6344cdd49cac44f352d5fd76c45c36..9e16f1d09515688e0fc7226918d197dd86d9cb7e 100644
--- a/substrate/frame/babe/src/lib.rs
+++ b/substrate/frame/babe/src/lib.rs
@@ -96,11 +96,11 @@ pub struct SameAuthoritiesForever;
 
 impl EpochChangeTrigger for SameAuthoritiesForever {
 	fn trigger<T: Config>(now: BlockNumberFor<T>) {
-		if <Pallet<T>>::should_epoch_change(now) {
-			let authorities = <Pallet<T>>::authorities();
+		if Pallet::<T>::should_epoch_change(now) {
+			let authorities = Authorities::<T>::get();
 			let next_authorities = authorities.clone();
 
-			<Pallet<T>>::enact_epoch_change(authorities, next_authorities, None);
+			Pallet::<T>::enact_epoch_change(authorities, next_authorities, None);
 		}
 	}
 }
@@ -185,12 +185,10 @@ pub mod pallet {
 
 	/// Current epoch index.
 	#[pallet::storage]
-	#[pallet::getter(fn epoch_index)]
 	pub type EpochIndex<T> = StorageValue<_, u64, ValueQuery>;
 
 	/// Current epoch authorities.
 	#[pallet::storage]
-	#[pallet::getter(fn authorities)]
 	pub type Authorities<T: Config> = StorageValue<
 		_,
 		WeakBoundedVec<(AuthorityId, BabeAuthorityWeight), T::MaxAuthorities>,
@@ -200,12 +198,10 @@ pub mod pallet {
 	/// The slot at which the first epoch actually started. This is 0
 	/// until the first block of the chain.
 	#[pallet::storage]
-	#[pallet::getter(fn genesis_slot)]
 	pub type GenesisSlot<T> = StorageValue<_, Slot, ValueQuery>;
 
 	/// Current slot number.
 	#[pallet::storage]
-	#[pallet::getter(fn current_slot)]
 	pub type CurrentSlot<T> = StorageValue<_, Slot, ValueQuery>;
 
 	/// The epoch randomness for the *current* epoch.
@@ -222,20 +218,19 @@ pub mod pallet {
 	// array size because the metadata API currently doesn't resolve the
 	// variable to its underlying value.
 	#[pallet::storage]
-	#[pallet::getter(fn randomness)]
 	pub type Randomness<T> = StorageValue<_, BabeRandomness, ValueQuery>;
 
 	/// Pending epoch configuration change that will be applied when the next epoch is enacted.
 	#[pallet::storage]
-	pub(super) type PendingEpochConfigChange<T> = StorageValue<_, NextConfigDescriptor>;
+	pub type PendingEpochConfigChange<T> = StorageValue<_, NextConfigDescriptor>;
 
 	/// Next epoch randomness.
 	#[pallet::storage]
-	pub(super) type NextRandomness<T> = StorageValue<_, BabeRandomness, ValueQuery>;
+	pub type NextRandomness<T> = StorageValue<_, BabeRandomness, ValueQuery>;
 
 	/// Next epoch authorities.
 	#[pallet::storage]
-	pub(super) type NextAuthorities<T: Config> = StorageValue<
+	pub type NextAuthorities<T: Config> = StorageValue<
 		_,
 		WeakBoundedVec<(AuthorityId, BabeAuthorityWeight), T::MaxAuthorities>,
 		ValueQuery,
@@ -251,11 +246,11 @@ pub mod pallet {
 	/// We reset all segments and return to `0` at the beginning of every
 	/// epoch.
 	#[pallet::storage]
-	pub(super) type SegmentIndex<T> = StorageValue<_, u32, ValueQuery>;
+	pub type SegmentIndex<T> = StorageValue<_, u32, ValueQuery>;
 
 	/// TWOX-NOTE: `SegmentIndex` is an increasing integer, so this is okay.
 	#[pallet::storage]
-	pub(super) type UnderConstruction<T: Config> = StorageMap<
+	pub type UnderConstruction<T: Config> = StorageMap<
 		_,
 		Twox64Concat,
 		u32,
@@ -266,16 +261,14 @@ pub mod pallet {
 	/// Temporary value (cleared at block finalization) which is `Some`
 	/// if per-block initialization has already been called for current block.
 	#[pallet::storage]
-	#[pallet::getter(fn initialized)]
-	pub(super) type Initialized<T> = StorageValue<_, Option<PreDigest>>;
+	pub type Initialized<T> = StorageValue<_, Option<PreDigest>>;
 
 	/// This field should always be populated during block processing unless
 	/// secondary plain slots are enabled (which don't contain a VRF output).
 	///
 	/// It is set in `on_finalize`, before it will contain the value from the last block.
 	#[pallet::storage]
-	#[pallet::getter(fn author_vrf_randomness)]
-	pub(super) type AuthorVrfRandomness<T> = StorageValue<_, Option<BabeRandomness>, ValueQuery>;
+	pub type AuthorVrfRandomness<T> = StorageValue<_, Option<BabeRandomness>, ValueQuery>;
 
 	/// The block numbers when the last and current epoch have started, respectively `N-1` and
 	/// `N`.
@@ -292,19 +285,17 @@ pub mod pallet {
 	/// on block finalization. Querying this storage entry outside of block
 	/// execution context should always yield zero.
 	#[pallet::storage]
-	#[pallet::getter(fn lateness)]
-	pub(super) type Lateness<T: Config> = StorageValue<_, BlockNumberFor<T>, ValueQuery>;
+	pub type Lateness<T: Config> = StorageValue<_, BlockNumberFor<T>, ValueQuery>;
 
 	/// The configuration for the current epoch. Should never be `None` as it is initialized in
 	/// genesis.
 	#[pallet::storage]
-	#[pallet::getter(fn epoch_config)]
-	pub(super) type EpochConfig<T> = StorageValue<_, BabeEpochConfiguration>;
+	pub type EpochConfig<T> = StorageValue<_, BabeEpochConfiguration>;
 
 	/// The configuration for the next epoch, `None` if the config will not change
 	/// (you can fallback to `EpochConfig` instead in that case).
 	#[pallet::storage]
-	pub(super) type NextEpochConfig<T> = StorageValue<_, BabeEpochConfiguration>;
+	pub type NextEpochConfig<T> = StorageValue<_, BabeEpochConfiguration>;
 
 	/// A list of the last 100 skipped epochs and the corresponding session index
 	/// when the epoch was skipped.
@@ -315,8 +306,7 @@ pub mod pallet {
 	/// a validator was the owner of a given key on a given session, and what the
 	/// active epoch index was during that session.
 	#[pallet::storage]
-	#[pallet::getter(fn skipped_epochs)]
-	pub(super) type SkippedEpochs<T> =
+	pub type SkippedEpochs<T> =
 		StorageValue<_, BoundedVec<(u64, SessionIndex), ConstU32<100>>, ValueQuery>;
 
 	#[derive(frame_support::DefaultNoBound)]
@@ -368,7 +358,7 @@ pub mod pallet {
 						.and_then(|(authority, _)| {
 							let public = authority.as_inner_ref();
 							let transcript = sp_consensus_babe::make_vrf_transcript(
-								&Self::randomness(),
+								&Randomness::<T>::get(),
 								CurrentSlot::<T>::get(),
 								EpochIndex::<T>::get(),
 							);
@@ -510,7 +500,7 @@ impl<T: Config> FindAuthor<u32> for Pallet<T> {
 
 impl<T: Config> IsMember<AuthorityId> for Pallet<T> {
 	fn is_member(authority_id: &AuthorityId) -> bool {
-		<Pallet<T>>::authorities().iter().any(|id| &id.0 == authority_id)
+		Authorities::<T>::get().iter().any(|id| &id.0 == authority_id)
 	}
 }
 
@@ -526,6 +516,47 @@ impl<T: Config> pallet_session::ShouldEndSession<BlockNumberFor<T>> for Pallet<T
 }
 
 impl<T: Config> Pallet<T> {
+	/// Public function to access epoch_index storage.
+	pub fn epoch_index() -> u64 {
+		EpochIndex::<T>::get()
+	}
+	/// Public function to access authorities storage.
+	pub fn authorities() -> WeakBoundedVec<(AuthorityId, BabeAuthorityWeight), T::MaxAuthorities> {
+		Authorities::<T>::get()
+	}
+	/// Public function to access genesis_slot storage.
+	pub fn genesis_slot() -> Slot {
+		GenesisSlot::<T>::get()
+	}
+	/// Public function to access current_slot storage.
+	pub fn current_slot() -> Slot {
+		CurrentSlot::<T>::get()
+	}
+	/// Public function to access randomness storage.
+	pub fn randomness() -> BabeRandomness {
+		Randomness::<T>::get()
+	}
+	/// Public function to access initialized storage.
+	pub fn initialized() -> Option<Option<PreDigest>> {
+		Initialized::<T>::get()
+	}
+	/// Public function to access author_vrf_randomness storage.
+	pub fn author_vrf_randomness() -> Option<BabeRandomness> {
+		AuthorVrfRandomness::<T>::get()
+	}
+	/// Public function to access lateness storage.
+	pub fn lateness() -> BlockNumberFor<T> {
+		Lateness::<T>::get()
+	}
+	/// Public function to access epoch_config storage.
+	pub fn epoch_config() -> Option<BabeEpochConfiguration> {
+		EpochConfig::<T>::get()
+	}
+	/// Public function to access skipped_epochs storage.
+	pub fn skipped_epochs() -> BoundedVec<(u64, SessionIndex), ConstU32<100>> {
+		SkippedEpochs::<T>::get()
+	}
+
 	/// Determine the BABE slot duration based on the Timestamp module configuration.
 	pub fn slot_duration() -> T::Moment {
 		// we double the minimum block-period so each author can always propose within
@@ -588,7 +619,7 @@ impl<T: Config> Pallet<T> {
 	) {
 		// PRECONDITION: caller has done initialization and is guaranteed
 		// by the session module to be called before this.
-		debug_assert!(Self::initialized().is_some());
+		debug_assert!(Initialized::<T>::get().is_some());
 
 		if authorities.is_empty() {
 			log::warn!(target: LOG_TARGET, "Ignoring empty epoch change.");
@@ -655,7 +686,7 @@ impl<T: Config> Pallet<T> {
 		NextAuthorities::<T>::put(&next_authorities);
 
 		// Update the start blocks of the previous and new current epoch.
-		<EpochStart<T>>::mutate(|(previous_epoch_start_block, current_epoch_start_block)| {
+		EpochStart::<T>::mutate(|(previous_epoch_start_block, current_epoch_start_block)| {
 			*previous_epoch_start_block = sp_std::mem::take(current_epoch_start_block);
 			*current_epoch_start_block = <frame_system::Pallet<T>>::block_number();
 		});
@@ -701,8 +732,8 @@ impl<T: Config> Pallet<T> {
 			epoch_index: EpochIndex::<T>::get(),
 			start_slot: Self::current_epoch_start(),
 			duration: T::EpochDuration::get(),
-			authorities: Self::authorities().into_inner(),
-			randomness: Self::randomness(),
+			authorities: Authorities::<T>::get().into_inner(),
+			randomness: Randomness::<T>::get(),
 			config: EpochConfig::<T>::get()
 				.expect("EpochConfig is initialized in genesis; we never `take` or `kill` it; qed"),
 		}
@@ -779,8 +810,8 @@ impl<T: Config> Pallet<T> {
 		// we use the same values as genesis because we haven't collected any
 		// randomness yet.
 		let next = NextEpochDescriptor {
-			authorities: Self::authorities().into_inner(),
-			randomness: Self::randomness(),
+			authorities: Authorities::<T>::get().into_inner(),
+			randomness: Randomness::<T>::get(),
 		};
 
 		Self::deposit_consensus(ConsensusLog::NextEpochData(next));
@@ -789,7 +820,7 @@ impl<T: Config> Pallet<T> {
 	fn initialize(now: BlockNumberFor<T>) {
 		// since `initialize` can be called twice (e.g. if session module is present)
 		// let's ensure that we only do the initialization once per block
-		let initialized = Self::initialized().is_some();
+		let initialized = Initialized::<T>::get().is_some();
 		if initialized {
 			return
 		}
@@ -940,7 +971,7 @@ impl<T: Config> frame_support::traits::EstimateNextSessionRotation<BlockNumberFo
 
 impl<T: Config> frame_support::traits::Lateness<BlockNumberFor<T>> for Pallet<T> {
 	fn lateness(&self) -> BlockNumberFor<T> {
-		Self::lateness()
+		Lateness::<T>::get()
 	}
 }
 
diff --git a/substrate/frame/babe/src/mock.rs b/substrate/frame/babe/src/mock.rs
index be38e3e7e5db5c0438688c584a81cc7ad3dc1913..e193a2e3b645446906b7c7b328faafaa59c382b8 100644
--- a/substrate/frame/babe/src/mock.rs
+++ b/substrate/frame/babe/src/mock.rs
@@ -213,7 +213,7 @@ pub fn go_to_block(n: u64, s: u64) {
 
 /// Slots will grow accordingly to blocks
 pub fn progress_to_block(n: u64) {
-	let mut slot = u64::from(Babe::current_slot()) + 1;
+	let mut slot = u64::from(CurrentSlot::<Test>::get()) + 1;
 	for i in System::block_number() + 1..=n {
 		go_to_block(i, slot);
 		slot += 1;
@@ -272,7 +272,8 @@ pub fn make_vrf_signature_and_randomness(
 	slot: Slot,
 	pair: &sp_consensus_babe::AuthorityPair,
 ) -> (VrfSignature, Randomness) {
-	let transcript = sp_consensus_babe::make_vrf_transcript(&Babe::randomness(), slot, 0);
+	let transcript =
+		sp_consensus_babe::make_vrf_transcript(&pallet_babe::Randomness::<Test>::get(), slot, 0);
 
 	let randomness =
 		pair.as_ref().make_bytes(sp_consensus_babe::RANDOMNESS_VRF_CONTEXT, &transcript);
diff --git a/substrate/frame/babe/src/tests.rs b/substrate/frame/babe/src/tests.rs
index e65f1844f88f9ffd9dc4e0a5c0f81e4f5e1c9459..b9a214ca105c846fae4be018149c7aba55c521e8 100644
--- a/substrate/frame/babe/src/tests.rs
+++ b/substrate/frame/babe/src/tests.rs
@@ -43,7 +43,7 @@ fn empty_randomness_is_correct() {
 
 #[test]
 fn initial_values() {
-	new_test_ext(4).execute_with(|| assert_eq!(Babe::authorities().len(), 4))
+	new_test_ext(4).execute_with(|| assert_eq!(Authorities::<Test>::get().len(), 4))
 }
 
 #[test]
@@ -68,25 +68,25 @@ fn first_block_epoch_zero_start() {
 
 		let pre_digest = make_primary_pre_digest(0, genesis_slot, vrf_signature);
 
-		assert_eq!(Babe::genesis_slot(), Slot::from(0));
+		assert_eq!(GenesisSlot::<Test>::get(), Slot::from(0));
 		System::reset_events();
 		System::initialize(&1, &Default::default(), &pre_digest);
 
 		// see implementation of the function for details why: we issue an
 		// epoch-change digest but don't do it via the normal session mechanism.
 		assert!(!Babe::should_end_session(1));
-		assert_eq!(Babe::genesis_slot(), genesis_slot);
-		assert_eq!(Babe::current_slot(), genesis_slot);
-		assert_eq!(Babe::epoch_index(), 0);
+		assert_eq!(GenesisSlot::<Test>::get(), genesis_slot);
+		assert_eq!(CurrentSlot::<Test>::get(), genesis_slot);
+		assert_eq!(EpochIndex::<Test>::get(), 0);
 
 		Babe::on_finalize(1);
 		let header = System::finalize();
 
-		assert_eq!(Babe::author_vrf_randomness(), Some(vrf_randomness));
+		assert_eq!(AuthorVrfRandomness::<Test>::get(), Some(vrf_randomness));
 		assert_eq!(SegmentIndex::<Test>::get(), 0);
 		assert_eq!(UnderConstruction::<Test>::get(0), vec![vrf_randomness]);
-		assert_eq!(Babe::randomness(), [0; 32]);
-		assert_eq!(Babe::author_vrf_randomness(), Some(vrf_randomness));
+		assert_eq!(Randomness::<Test>::get(), [0; 32]);
+		assert_eq!(AuthorVrfRandomness::<Test>::get(), Some(vrf_randomness));
 		assert_eq!(NextRandomness::<Test>::get(), [0; 32]);
 
 		assert_eq!(header.digest.logs.len(), 2);
@@ -95,8 +95,8 @@ fn first_block_epoch_zero_start() {
 
 		let consensus_log = sp_consensus_babe::ConsensusLog::NextEpochData(
 			sp_consensus_babe::digests::NextEpochDescriptor {
-				authorities: Babe::authorities().into_inner(),
-				randomness: Babe::randomness(),
+				authorities: Authorities::<Test>::get().into_inner(),
+				randomness: Randomness::<Test>::get(),
 			},
 		);
 		let consensus_digest = DigestItem::Consensus(BABE_ENGINE_ID, consensus_log.encode());
@@ -118,19 +118,19 @@ fn current_slot_is_processed_on_initialization() {
 
 		System::reset_events();
 		System::initialize(&1, &Default::default(), &pre_digest);
-		assert_eq!(Babe::current_slot(), Slot::from(0));
-		assert!(Babe::initialized().is_none());
+		assert_eq!(CurrentSlot::<Test>::get(), Slot::from(0));
+		assert!(Initialized::<Test>::get().is_none());
 
 		// current slot is updated on initialization
 		Babe::initialize(1);
-		assert_eq!(Babe::current_slot(), genesis_slot);
-		assert!(Babe::initialized().is_some());
+		assert_eq!(CurrentSlot::<Test>::get(), genesis_slot);
+		assert!(Initialized::<Test>::get().is_some());
 		// but author vrf randomness isn't
-		assert_eq!(Babe::author_vrf_randomness(), None);
+		assert_eq!(AuthorVrfRandomness::<Test>::get(), None);
 
 		// instead it is updated on block finalization
 		Babe::on_finalize(1);
-		assert_eq!(Babe::author_vrf_randomness(), Some(vrf_randomness));
+		assert_eq!(AuthorVrfRandomness::<Test>::get(), Some(vrf_randomness));
 	})
 }
 
@@ -151,16 +151,16 @@ where
 
 		// author vrf randomness is not updated on initialization
 		Babe::initialize(1);
-		assert_eq!(Babe::author_vrf_randomness(), None);
+		assert_eq!(AuthorVrfRandomness::<Test>::get(), None);
 
 		// instead it is updated on block finalization to account for any
 		// epoch changes that might happen during the block
 		Babe::on_finalize(1);
-		assert_eq!(Babe::author_vrf_randomness(), Some(vrf_randomness));
+		assert_eq!(AuthorVrfRandomness::<Test>::get(), Some(vrf_randomness));
 
 		// and it is kept after finalizing the block
 		System::finalize();
-		assert_eq!(Babe::author_vrf_randomness(), Some(vrf_randomness));
+		assert_eq!(AuthorVrfRandomness::<Test>::get(), Some(vrf_randomness));
 	})
 }
 
@@ -182,14 +182,14 @@ fn no_author_vrf_output_for_secondary_plain() {
 
 		System::reset_events();
 		System::initialize(&1, &Default::default(), &secondary_plain_pre_digest);
-		assert_eq!(Babe::author_vrf_randomness(), None);
+		assert_eq!(AuthorVrfRandomness::<Test>::get(), None);
 
 		Babe::initialize(1);
-		assert_eq!(Babe::author_vrf_randomness(), None);
+		assert_eq!(AuthorVrfRandomness::<Test>::get(), None);
 
 		Babe::on_finalize(1);
 		System::finalize();
-		assert_eq!(Babe::author_vrf_randomness(), None);
+		assert_eq!(AuthorVrfRandomness::<Test>::get(), None);
 	})
 }
 
@@ -210,14 +210,14 @@ fn can_predict_next_epoch_change() {
 		assert_eq!(<Test as Config>::EpochDuration::get(), 3);
 		// this sets the genesis slot to 6;
 		go_to_block(1, 6);
-		assert_eq!(*Babe::genesis_slot(), 6);
-		assert_eq!(*Babe::current_slot(), 6);
-		assert_eq!(Babe::epoch_index(), 0);
+		assert_eq!(*GenesisSlot::<Test>::get(), 6);
+		assert_eq!(*CurrentSlot::<Test>::get(), 6);
+		assert_eq!(EpochIndex::<Test>::get(), 0);
 
 		progress_to_block(5);
 
-		assert_eq!(Babe::epoch_index(), 5 / 3);
-		assert_eq!(*Babe::current_slot(), 10);
+		assert_eq!(EpochIndex::<Test>::get(), 5 / 3);
+		assert_eq!(*CurrentSlot::<Test>::get(), 10);
 
 		// next epoch change will be at
 		assert_eq!(*Babe::current_epoch_start(), 9); // next change will be 12, 2 slots from now
@@ -266,9 +266,9 @@ fn can_enact_next_config() {
 		assert_eq!(<Test as Config>::EpochDuration::get(), 3);
 		// this sets the genesis slot to 6;
 		go_to_block(1, 6);
-		assert_eq!(*Babe::genesis_slot(), 6);
-		assert_eq!(*Babe::current_slot(), 6);
-		assert_eq!(Babe::epoch_index(), 0);
+		assert_eq!(*GenesisSlot::<Test>::get(), 6);
+		assert_eq!(*CurrentSlot::<Test>::get(), 6);
+		assert_eq!(EpochIndex::<Test>::get(), 0);
 		go_to_block(2, 7);
 
 		let current_config = BabeEpochConfiguration {
@@ -431,7 +431,7 @@ fn report_equivocation_current_session_works() {
 	ext.execute_with(|| {
 		start_era(1);
 
-		let authorities = Babe::authorities();
+		let authorities = Authorities::<Test>::get();
 		let validators = Session::validators();
 
 		// make sure that all authorities have the same balance
@@ -508,7 +508,7 @@ fn report_equivocation_old_session_works() {
 	ext.execute_with(|| {
 		start_era(1);
 
-		let authorities = Babe::authorities();
+		let authorities = Authorities::<Test>::get();
 
 		// we will use the validator at index 0 as the offending authority
 		let offending_validator_index = 1;
@@ -566,7 +566,7 @@ fn report_equivocation_invalid_key_owner_proof() {
 	ext.execute_with(|| {
 		start_era(1);
 
-		let authorities = Babe::authorities();
+		let authorities = Authorities::<Test>::get();
 
 		// we will use the validator at index 0 as the offending authority
 		let offending_validator_index = 0;
@@ -629,7 +629,7 @@ fn report_equivocation_invalid_equivocation_proof() {
 	ext.execute_with(|| {
 		start_era(1);
 
-		let authorities = Babe::authorities();
+		let authorities = Authorities::<Test>::get();
 
 		// we will use the validator at index 0 as the offending authority
 		let offending_validator_index = 0;
@@ -734,7 +734,7 @@ fn report_equivocation_validate_unsigned_prevents_duplicates() {
 	ext.execute_with(|| {
 		start_era(1);
 
-		let authorities = Babe::authorities();
+		let authorities = Authorities::<Test>::get();
 
 		// generate and report an equivocation for the validator at index 0
 		let offending_validator_index = 0;
@@ -848,7 +848,7 @@ fn report_equivocation_after_skipped_epochs_works() {
 		assert_eq!(SkippedEpochs::<Test>::get(), vec![(10, 1)]);
 
 		// generate an equivocation proof for validator at index 1
-		let authorities = Babe::authorities();
+		let authorities = Authorities::<Test>::get();
 		let offending_validator_index = 1;
 		let offending_authority_pair = pairs
 			.into_iter()