diff --git a/prdoc/pr_3589.prdoc b/prdoc/pr_3589.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..98b9b1039ab49f1dc62580d56327bf7944ed3372
--- /dev/null
+++ b/prdoc/pr_3589.prdoc
@@ -0,0 +1,10 @@
+title: Removed `pallet::getter` usage from `pallet-im-online`
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      This PR removes `pallet::getter` usage from `pallet-im-online`, and updates dependant code accordingly.
+      The syntax `StorageItem::<T, I>::get()` should be used instead.
+
+crates: 
+  - name: pallet-im-online
diff --git a/substrate/frame/im-online/src/lib.rs b/substrate/frame/im-online/src/lib.rs
index f14093aa09afa98da1c37b0e961319e80821fe40..239b47834d1f8b1625a186e4a8f90e9861bfa303 100644
--- a/substrate/frame/im-online/src/lib.rs
+++ b/substrate/frame/im-online/src/lib.rs
@@ -338,26 +338,22 @@ pub mod pallet {
 	/// progress estimate from `NextSessionRotation`, as those estimates should be
 	/// more accurate then the value we calculate for `HeartbeatAfter`.
 	#[pallet::storage]
-	#[pallet::getter(fn heartbeat_after)]
-	pub(super) type HeartbeatAfter<T: Config> = StorageValue<_, BlockNumberFor<T>, ValueQuery>;
+	pub type HeartbeatAfter<T: Config> = StorageValue<_, BlockNumberFor<T>, ValueQuery>;
 
 	/// The current set of keys that may issue a heartbeat.
 	#[pallet::storage]
-	#[pallet::getter(fn keys)]
-	pub(super) type Keys<T: Config> =
+	pub type Keys<T: Config> =
 		StorageValue<_, WeakBoundedVec<T::AuthorityId, T::MaxKeys>, ValueQuery>;
 
 	/// For each session index, we keep a mapping of `SessionIndex` and `AuthIndex`.
 	#[pallet::storage]
-	#[pallet::getter(fn received_heartbeats)]
-	pub(super) type ReceivedHeartbeats<T: Config> =
+	pub type ReceivedHeartbeats<T: Config> =
 		StorageDoubleMap<_, Twox64Concat, SessionIndex, Twox64Concat, AuthIndex, bool>;
 
 	/// For each session index, we keep a mapping of `ValidatorId<T>` to the
 	/// number of blocks authored by the given authority.
 	#[pallet::storage]
-	#[pallet::getter(fn authored_blocks)]
-	pub(super) type AuthoredBlocks<T: Config> = StorageDoubleMap<
+	pub type AuthoredBlocks<T: Config> = StorageDoubleMap<
 		_,
 		Twox64Concat,
 		SessionIndex,
diff --git a/substrate/frame/im-online/src/tests.rs b/substrate/frame/im-online/src/tests.rs
index 7efca926eb0dc4f0098af01967b5214ab371e143..6f5a14d7e7fb5dc3e73e1660a8f55d9916f32be9 100644
--- a/substrate/frame/im-online/src/tests.rs
+++ b/substrate/frame/im-online/src/tests.rs
@@ -26,10 +26,7 @@ use sp_core::offchain::{
 	testing::{TestOffchainExt, TestTransactionPoolExt},
 	OffchainDbExt, OffchainWorkerExt, TransactionPoolExt,
 };
-use sp_runtime::{
-	testing::UintAuthorityId,
-	transaction_validity::{InvalidTransaction, TransactionValidityError},
-};
+use sp_runtime::testing::UintAuthorityId;
 
 #[test]
 fn test_unresponsiveness_slash_fraction() {
@@ -267,14 +264,14 @@ fn should_cleanup_received_heartbeats_on_session_end() {
 		let _ = heartbeat(1, 2, 0, 1.into(), Session::validators()).unwrap();
 
 		// the heartbeat is stored
-		assert!(!ImOnline::received_heartbeats(&2, &0).is_none());
+		assert!(!super::pallet::ReceivedHeartbeats::<Runtime>::get(2, 0).is_none());
 
 		advance_session();
 
 		// after the session has ended we have already processed the heartbeat
 		// message, so any messages received on the previous session should have
 		// been pruned.
-		assert!(ImOnline::received_heartbeats(&2, &0).is_none());
+		assert!(super::pallet::ReceivedHeartbeats::<Runtime>::get(2, 0).is_none());
 	});
 }