diff --git a/core/src/shred_fetch_stage.rs b/core/src/shred_fetch_stage.rs
index bbb130573cab9a..703167b0b44ac1 100644
--- a/core/src/shred_fetch_stage.rs
+++ b/core/src/shred_fetch_stage.rs
@@ -10,7 +10,9 @@ use {
     solana_perf::packet::{PacketBatch, PacketBatchRecycler, PacketFlags, PACKETS_PER_BATCH},
     solana_runtime::bank_forks::BankForks,
     solana_sdk::{
-        clock::DEFAULT_MS_PER_SLOT,
+        clock::{Slot, DEFAULT_MS_PER_SLOT},
+        epoch_schedule::EpochSchedule,
+        feature_set::{self, FeatureSet},
         packet::{Meta, PACKET_DATA_SIZE},
         pubkey::Pubkey,
     },
@@ -50,12 +52,20 @@ impl ShredFetchStage {
             .as_ref()
             .map(|(_, cluster_info)| cluster_info.keypair().clone());
 
-        let (mut last_root, mut slots_per_epoch, mut last_slot) = {
+        let (
+            mut last_root,
+            mut slots_per_epoch,
+            mut feature_set,
+            mut epoch_schedule,
+            mut last_slot,
+        ) = {
             let bank_forks_r = bank_forks.read().unwrap();
             let root_bank = bank_forks_r.root_bank();
             (
                 root_bank.slot(),
                 root_bank.get_slots_in_epoch(root_bank.epoch()),
+                root_bank.feature_set.clone(),
+                *root_bank.epoch_schedule(),
                 bank_forks_r.highest_slot(),
             )
         };
@@ -69,6 +79,8 @@ impl ShredFetchStage {
                     last_slot = bank_forks_r.highest_slot();
                     bank_forks_r.root_bank()
                 };
+                feature_set = root_bank.feature_set.clone();
+                epoch_schedule = *root_bank.epoch_schedule();
                 last_root = root_bank.slot();
                 slots_per_epoch = root_bank.get_slots_in_epoch(root_bank.epoch());
                 keypair = repair_context
@@ -92,10 +104,19 @@ impl ShredFetchStage {
 
             // Limit shreds to 2 epochs away.
             let max_slot = last_slot + 2 * slots_per_epoch;
+            let should_drop_legacy_shreds =
+                |shred_slot| should_drop_legacy_shreds(shred_slot, &feature_set, &epoch_schedule);
             let turbine_disabled = turbine_disabled.load(Ordering::Relaxed);
             for packet in packet_batch.iter_mut().filter(|p| !p.meta().discard()) {
                 if turbine_disabled
-                    || should_discard_shred(packet, last_root, max_slot, shred_version, &mut stats)
+                    || should_discard_shred(
+                        packet,
+                        last_root,
+                        max_slot,
+                        shred_version,
+                        should_drop_legacy_shreds,
+                        &mut stats,
+                    )
                 {
                     packet.meta_mut().set_discard(true);
                 } else {
@@ -373,6 +394,22 @@ pub(crate) fn receive_repair_quic_packets(
     }
 }
 
+#[must_use]
+fn should_drop_legacy_shreds(
+    shred_slot: Slot,
+    feature_set: &FeatureSet,
+    epoch_schedule: &EpochSchedule,
+) -> bool {
+    match feature_set.activated_slot(&feature_set::drop_legacy_shreds::id()) {
+        None => false,
+        Some(feature_slot) => {
+            let feature_epoch = epoch_schedule.get_epoch(feature_slot);
+            let shred_epoch = epoch_schedule.get_epoch(shred_slot);
+            feature_epoch < shred_epoch
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use {
@@ -413,6 +450,7 @@ mod tests {
             last_root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats,
         ));
         let coding = solana_ledger::shred::Shredder::generate_coding_shreds(
@@ -426,6 +464,7 @@ mod tests {
             last_root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats,
         ));
     }
@@ -447,6 +486,7 @@ mod tests {
             last_root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats,
         ));
         assert_eq!(stats.index_overrun, 1);
@@ -468,12 +508,18 @@ mod tests {
             3,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats,
         ));
         assert_eq!(stats.slot_out_of_range, 1);
 
         assert!(should_discard_shred(
-            &packet, last_root, max_slot, /*shred_version:*/ 345, &mut stats,
+            &packet,
+            last_root,
+            max_slot,
+            345,       // shred_version
+            |_| false, // should_drop_legacy_shreds
+            &mut stats,
         ));
         assert_eq!(stats.shred_version_mismatch, 1);
 
@@ -483,6 +529,7 @@ mod tests {
             last_root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats,
         ));
 
@@ -504,6 +551,7 @@ mod tests {
             last_root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats,
         ));
 
@@ -515,6 +563,7 @@ mod tests {
             last_root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats,
         ));
     }
diff --git a/ledger/src/shred.rs b/ledger/src/shred.rs
index 5fda160e29b976..e65b155afe3974 100644
--- a/ledger/src/shred.rs
+++ b/ledger/src/shred.rs
@@ -893,6 +893,7 @@ pub fn should_discard_shred(
     root: Slot,
     max_slot: Slot,
     shred_version: u16,
+    should_drop_legacy_shreds: impl Fn(Slot) -> bool,
     stats: &mut ShredFetchStats,
 ) -> bool {
     debug_assert!(root < max_slot);
@@ -967,7 +968,11 @@ pub fn should_discard_shred(
         }
     }
     match shred_variant {
-        ShredVariant::LegacyCode | ShredVariant::LegacyData => (),
+        ShredVariant::LegacyCode | ShredVariant::LegacyData => {
+            if should_drop_legacy_shreds(slot) {
+                return true;
+            }
+        }
         ShredVariant::MerkleCode(_) => {
             stats.num_shreds_merkle_code = stats.num_shreds_merkle_code.saturating_add(1);
         }
@@ -1171,6 +1176,7 @@ mod tests {
             root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats
         ));
         assert_eq!(stats, ShredFetchStats::default());
@@ -1181,6 +1187,7 @@ mod tests {
             root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats
         ));
         assert_eq!(stats.index_overrun, 1);
@@ -1191,6 +1198,7 @@ mod tests {
             root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats
         ));
         assert_eq!(stats.index_overrun, 2);
@@ -1201,6 +1209,7 @@ mod tests {
             root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats
         ));
         assert_eq!(stats.index_overrun, 3);
@@ -1211,6 +1220,7 @@ mod tests {
             root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats
         ));
         assert_eq!(stats.index_overrun, 4);
@@ -1221,6 +1231,7 @@ mod tests {
             root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats
         ));
         assert_eq!(stats.bad_parent_offset, 1);
@@ -1241,6 +1252,7 @@ mod tests {
             root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats
         ));
 
@@ -1260,6 +1272,7 @@ mod tests {
             root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats
         ));
         assert_eq!(1, stats.index_out_of_bounds);
@@ -1280,6 +1293,7 @@ mod tests {
             root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats
         ));
         packet.buffer_mut()[OFFSET_OF_SHRED_VARIANT] = u8::MAX;
@@ -1289,6 +1303,7 @@ mod tests {
             root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats
         ));
         assert_eq!(1, stats.bad_shred_type);
@@ -1300,6 +1315,7 @@ mod tests {
             root,
             max_slot,
             shred_version,
+            |_| false, // should_drop_legacy_shreds
             &mut stats
         ));
         assert_eq!(1, stats.bad_shred_type);
diff --git a/sdk/src/feature_set.rs b/sdk/src/feature_set.rs
index 44d81f52d1d19c..34dfdbcbbcbc29 100644
--- a/sdk/src/feature_set.rs
+++ b/sdk/src/feature_set.rs
@@ -728,6 +728,10 @@ pub mod enable_zk_transfer_with_fee {
     solana_sdk::declare_id!("zkNLP7EQALfC1TYeB3biDU7akDckj8iPkvh9y2Mt2K3");
 }
 
+pub mod drop_legacy_shreds {
+    solana_sdk::declare_id!("GV49KKQdBNaiv2pgqhS2Dy3GWYJGXMTVYbYkdk91orRy");
+}
+
 lazy_static! {
     /// Map of feature identifiers to user-visible description
     pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
@@ -905,6 +909,7 @@ lazy_static! {
         (update_hashes_per_tick6::id(), "Update desired hashes per tick to 10M"),
         (validate_fee_collector_account::id(), "validate fee collector account #33888"),
         (enable_zk_transfer_with_fee::id(), "enable Zk Token proof program transfer with fee"),
+        (drop_legacy_shreds::id(), "drops legacy shreds #34328"),
         /*************** ADD NEW FEATURES HERE ***************/
     ]
     .iter()