diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Changelog
 
+## [1.2.0.3] - 2023-01-11
+
+- Drop support for `hspec < 2.10`, `hspec-core < 2.10`, `tasty < 1.3`, and `tasty-quickcheck < 0.9.1`. This was done to
+  eliminate CPP and reduce maintenance burden. Moving forward, this library will opt to tighten compatibility bounds
+  when dependencies make breaking changes, rather than reintroduce CPP.
+
 ## [1.2.0.2] - 2023-01-10
 
 - Fix build when `tasty-quickcheck < 0.9.1`
diff --git a/src/Test/Tasty/Hspec.hs b/src/Test/Tasty/Hspec.hs
--- a/src/Test/Tasty/Hspec.hs
+++ b/src/Test/Tasty/Hspec.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE CPP #-}
-
 -- | @hspec@ and @tasty@ serve similar purposes; consider using one or the
 -- other.
 --
@@ -26,12 +24,11 @@
 import qualified Test.Hspec.Core.Formatters as Hspec.Core.Formatters
 import qualified Test.Hspec.Core.Spec as Hspec.Core.Spec
 import qualified Test.Tasty as Tasty
-import Test.Tasty.Hspec.Compat
 import qualified Test.Tasty.Options as Tasty.Options
 import qualified Test.Tasty.Providers as Tasty.Providers
-import qualified Test.Tasty.QuickCheck as TQC
+import qualified Test.Tasty.QuickCheck as Tasty.QuickCheck
 import qualified Test.Tasty.Runners as Tasty.Runners
-import qualified Test.Tasty.SmallCheck as TSC
+import qualified Test.Tasty.SmallCheck as Tasty.SmallCheck
 
 -- $examples
 --
@@ -88,17 +85,17 @@
   -- Here we do as hspec does, which is pre-process a spec by focusing the whole thing, which is a no-op if
   -- anything inside is already focused, but otherwise focuses every item. Then, when creating a tasty test tree,
   -- we just toss the unfocused items.
-  trees <- runSpecM (focus spec)
+  (_configBuilder, trees) <- Hspec.Core.Spec.runSpecM (Hspec.focus spec)
   pure (mapMaybe specTreeToTestTree trees)
 
 specTreeToTestTree :: Hspec.Core.Spec.SpecTree () -> Maybe Tasty.TestTree
 specTreeToTestTree = \case
-  Node name trees -> pure (Tasty.testGroup name (mapMaybe specTreeToTestTree trees))
-  NodeWithCleanup cleanup trees -> do
-    tree <- specTreeToTestTree (Node "(unnamed)" trees)
-    pure (Tasty.Runners.WithResource (Tasty.Runners.ResourceSpec (pure ()) (twiddleCleanup cleanup)) (const tree))
-  Leaf item -> do
-    guard (itemIsFocused item)
+  Hspec.Core.Spec.Node name trees -> pure (Tasty.testGroup name (mapMaybe specTreeToTestTree trees))
+  Hspec.Core.Spec.NodeWithCleanup _loc cleanup trees -> do
+    tree <- specTreeToTestTree (Hspec.Core.Spec.Node "(unnamed)" trees)
+    pure (Tasty.Runners.WithResource (Tasty.Runners.ResourceSpec (pure ()) (const cleanup)) (const tree))
+  Hspec.Core.Spec.Leaf item -> do
+    guard (Hspec.Core.Spec.itemIsFocused item)
     pure (Tasty.Providers.singleTest (Hspec.Core.Spec.itemRequirement item) (Item item))
 
 newtype Item
@@ -107,13 +104,18 @@
 
 instance Tasty.Providers.IsTest Item where
   run opts (Item item) progress = do
-    qcArgs <- optionSetToQuickCheckArgs opts
+    (_, qcArgs) <- Tasty.QuickCheck.optionSetToArgs opts
+    -- optionSetToQuickCheckArgs :: Tasty.OptionSet -> IO QuickCheck.Args
+    -- optionSetToQuickCheckArgs opts =
+    --   snd <$> Tasty.QuickCheck.optionSetToArgs opts
     let params =
           Hspec.Core.Spec.Params
             { Hspec.Core.Spec.paramsQuickCheckArgs = qcArgs,
-              Hspec.Core.Spec.paramsSmallCheckDepth = optionSetToSmallCheckDepth opts
+              Hspec.Core.Spec.paramsSmallCheckDepth =
+                case Tasty.Options.lookupOption opts of
+                  Tasty.SmallCheck.SmallCheckDepth depth -> Just depth
             }
-    Hspec.Core.Spec.Result _ result <- itemExample item params ($ ()) progress'
+    Hspec.Core.Spec.Result _ result <- Hspec.Core.Spec.itemExample item params ($ ()) progress'
     pure
       ( case result of
           Hspec.Core.Spec.Success -> Tasty.Providers.testPassed ""
@@ -147,11 +149,11 @@
   testOptions =
     pure
       [ Tasty.Options.Option (Proxy :: Proxy TreatPendingAs),
-        Tasty.Options.Option (Proxy :: Proxy TQC.QuickCheckTests),
-        Tasty.Options.Option (Proxy :: Proxy TQC.QuickCheckReplay),
-        Tasty.Options.Option (Proxy :: Proxy TQC.QuickCheckMaxSize),
-        Tasty.Options.Option (Proxy :: Proxy TQC.QuickCheckMaxRatio),
-        Tasty.Options.Option (Proxy :: Proxy TSC.SmallCheckDepth)
+        Tasty.Options.Option (Proxy :: Proxy Tasty.QuickCheck.QuickCheckTests),
+        Tasty.Options.Option (Proxy :: Proxy Tasty.QuickCheck.QuickCheckReplay),
+        Tasty.Options.Option (Proxy :: Proxy Tasty.QuickCheck.QuickCheckMaxSize),
+        Tasty.Options.Option (Proxy :: Proxy Tasty.QuickCheck.QuickCheckMaxRatio),
+        Tasty.Options.Option (Proxy :: Proxy Tasty.SmallCheck.SmallCheckDepth)
       ]
 
 -- | How to treat @hspec@ pending tests.
@@ -180,7 +182,5 @@
   optionHelp =
     pure "How to treat pending hspec tests ('failure' or 'success')"
 
-#if MIN_VERSION_tasty(1,3,0)
   showDefaultValue _ =
     Just "failure"
-#endif
diff --git a/src/Test/Tasty/Hspec/Compat.hs b/src/Test/Tasty/Hspec/Compat.hs
deleted file mode 100644
--- a/src/Test/Tasty/Hspec/Compat.hs
+++ /dev/null
@@ -1,135 +0,0 @@
-{-# LANGUAGE CPP #-}
-
-module Test.Tasty.Hspec.Compat
-  ( itemExample,
-    itemIsFocused,
-    focus,
-    optionSetToQuickCheckArgs,
-    optionSetToSmallCheckDepth,
-    runSpecM,
-    twiddleCleanup,
-
-    pattern Leaf,
-    pattern Node,
-    pattern NodeWithCleanup,
-  )
-where
-
-import qualified Test.Hspec as Hspec
-import qualified Test.Hspec.Core.Spec as Hspec
-import qualified Test.QuickCheck as QuickCheck
-import qualified Test.Tasty.Options as Tasty
-import qualified Test.Tasty.QuickCheck as Tasty.QuickCheck
-import qualified Test.Tasty.SmallCheck as Tasty.SmallCheck
-#if MIN_VERSION_hspec_core(2,10,0)
-import Data.Monoid (Endo)
-import qualified Test.Hspec.Core.Runner as Hspec.Core.Runner
-#endif
-
-{-# COMPLETE Leaf, Node, NodeWithCleanup #-}
-
-pattern Leaf :: a -> Hspec.Tree c a
-pattern Leaf item <-
-  Hspec.Leaf item
-
-pattern Node :: String -> [Hspec.Tree c a] -> Hspec.Tree c a
-pattern Node name trees =
-  Hspec.Node name trees
-
-pattern NodeWithCleanup :: c -> [Hspec.Tree c a] -> Hspec.Tree c a
-pattern NodeWithCleanup cleanup trees <-
-#if MIN_VERSION_hspec(2,8,0)
-  Hspec.NodeWithCleanup _loc cleanup trees
-#else
-  Hspec.NodeWithCleanup cleanup trees
-#endif
-
-itemExample :: Hspec.Item a -> Hspec.Params -> (Hspec.ActionWith a -> IO ()) -> Hspec.ProgressCallback -> IO Hspec.Result
-itemExample item =
-  case item of
-#if MIN_VERSION_hspec(2,6,0)
-    Hspec.Item _ _ _ _ example -> example
-#else
-    Hspec.Item _ _ _ example -> example
-#endif
-
-itemIsFocused :: Hspec.Item a -> Bool
-itemIsFocused =
-#if MIN_VERSION_hspec(2,6,0)
-  Hspec.itemIsFocused
-#else
-  const True
-#endif
-
-focus :: Hspec.Spec -> Hspec.Spec
-focus =
-#if MIN_VERSION_hspec(2,6,0)
-  Hspec.focus
-#else
-  id
-#endif
-
-optionSetToQuickCheckArgs :: Tasty.OptionSet -> IO QuickCheck.Args
-optionSetToQuickCheckArgs opts =
-#if MIN_VERSION_tasty_quickcheck(0,9,1)
-  snd <$> Tasty.QuickCheck.optionSetToArgs opts
-#else
-  pure
-    QuickCheck.stdArgs
-      { QuickCheck.chatty = False,
-        QuickCheck.maxDiscardRatio = max_ratio,
-        QuickCheck.maxSize = max_size,
-        QuickCheck.maxSuccess = num_tests,
-        QuickCheck.replay = replay
-      }
-  where
-    Tasty.QuickCheck.QuickCheckTests num_tests = Tasty.lookupOption opts
-    Tasty.QuickCheck.QuickCheckReplay replay = Tasty.lookupOption opts
-    Tasty.QuickCheck.QuickCheckMaxSize max_size = Tasty.lookupOption opts
-    Tasty.QuickCheck.QuickCheckMaxRatio max_ratio = Tasty.lookupOption opts
-#endif
-
--- In hspec-core-2.10.0, Int changed to Maybe Int
-optionSetToSmallCheckDepth ::
-  Tasty.OptionSet ->
-#if MIN_VERSION_hspec_core(2,10,0)
-  Maybe
-#endif
-  Int
-optionSetToSmallCheckDepth opts =
-  case Tasty.lookupOption opts of
-    Tasty.SmallCheck.SmallCheckDepth depth ->
-#if MIN_VERSION_hspec_core(2,10,0)
-      Just
-#endif
-      depth
-
--- In hspec-core-2.10.0, runSpecM started returning an Endo Config, which we don't need. (Right? :shrug:)
-runSpecM :: Hspec.SpecWith a -> IO [Hspec.SpecTree a]
-runSpecM spec = do
-#if MIN_VERSION_hspec_core(2,10,0)
-  (_ :: Endo Hspec.Core.Runner.Config, trees) <- Hspec.runSpecM spec
-  pure trees
-#else
-  Hspec.runSpecM spec
-#endif
-
--- In hspec-core-2.10.0, the spec SpecTree type alias changed from
---
---   type SpecTree a = Tree (a -> IO ()) (Item a)
---
--- to
---
---   type SpecTree a = Tree (IO ()) (Item a)
---
--- So we have a function that "twiddles" the cleanup action (at monomorphic type `SpecTree ()`), which always returns a
--- value of type `() -> IO ()`
-#if MIN_VERSION_hspec_core(2,10,0)
-twiddleCleanup :: IO () -> () -> IO ()
-twiddleCleanup =
-  const
-#else
-twiddleCleanup :: (() -> IO ()) -> () -> IO ()
-twiddleCleanup =
-  id
-#endif
diff --git a/tasty-hspec.cabal b/tasty-hspec.cabal
--- a/tasty-hspec.cabal
+++ b/tasty-hspec.cabal
@@ -1,18 +1,18 @@
-cabal-version:       2.0
+cabal-version:       2.2
 name:                tasty-hspec
-version:             1.2.0.2
+version:             1.2.0.3
 synopsis:            Hspec support for the Tasty test framework.
 description:         This package provides a Tasty provider for Hspec test
                      suites.
 
 homepage:            https://github.com/mitchellwrosen/tasty-hspec
-license:             BSD3
+license:             BSD-3-Clause
 license-file:        LICENSE
 author:              Mitchell Rosen
 maintainer:          mitchellwrosen@gmail.com
 category:            Testing
 build-type:          Simple
-tested-with:         GHC == 9.0.2, GHC == 9.2.4, GHC == 9.4.1
+tested-with:         GHC == 9.0.2, GHC == 9.2.5, GHC == 9.4.4
 
 extra-source-files:
   .gitignore
@@ -27,18 +27,16 @@
 library
   build-depends:
     base ^>= 4.9 || ^>= 4.10 || ^>= 4.11 || ^>= 4.12 || ^>= 4.13 || ^>= 4.14 || ^>= 4.15 || ^>= 4.16 || ^>= 4.17,
-    hspec ^>= 2.5 || ^>= 2.6 || ^>= 2.7 || ^>= 2.8 || ^>= 2.9 || ^>= 2.10,
-    hspec-core ^>= 2.5 || ^>= 2.6 || ^>= 2.7 || ^>= 2.8 || ^>= 2.9 || ^>= 2.10,
+    hspec ^>= 2.10,
+    hspec-core ^>= 2.10,
     QuickCheck ^>= 2.7 || ^>= 2.8 || ^>= 2.9 || ^>= 2.10 || ^>= 2.11 || ^>= 2.12 || ^>= 2.13 || ^>= 2.14,
-    tasty ^>= 0.8 || ^>= 0.9 || ^>= 0.10 || ^>= 0.11 || ^>= 0.12 || ^>= 1.0 || ^>= 1.1 || ^>= 1.2 || ^>= 1.3 || ^>= 1.4,
+    tasty ^>= 1.3 || ^>= 1.4,
     tasty-smallcheck >= 0.1 && < 0.9,
-    -- 0.9 is missing 'optionSetToArgs'
-    tasty-quickcheck >=0.3 && <0.9 || ^>=0.9.1 || ^>= 0.10
+    tasty-quickcheck ^>= 0.9.1 || ^>= 0.10,
   if impl(ghc < 7.8)
     build-depends: tagged >= 0.2
   default-extensions:
     LambdaCase
-    PatternSynonyms
     ScopedTypeVariables
   default-language: Haskell2010
   exposed-modules: Test.Tasty.Hspec
@@ -46,4 +44,3 @@
   if impl(ghc >= 8.0)
     ghc-options: -Wcompat
   hs-source-dirs: src
-  other-modules: Test.Tasty.Hspec.Compat
