diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+# v1.4.2.0
+
+* Drop support for GHC 8.10 + 9.0 + 9.2
+* Add support for GHC 9.8
+
 # v1.4.1.0
 
 * Add support for GHC 9.6
diff --git a/aeson-schemas.cabal b/aeson-schemas.cabal
--- a/aeson-schemas.cabal
+++ b/aeson-schemas.cabal
@@ -1,11 +1,11 @@
 cabal-version: >= 1.10
 
--- This file has been generated from package.yaml by hpack version 0.35.2.
+-- This file has been generated from package.yaml by hpack version 0.36.0.
 --
 -- see: https://github.com/sol/hpack
 
 name:           aeson-schemas
-version:        1.4.1.0
+version:        1.4.2.0
 synopsis:       Easily consume JSON data on-demand with type-safety
 description:    Parse JSON data easily and safely without defining new data types. Useful
                 for deeply nested JSON data, which is difficult to parse using the default
@@ -39,10 +39,10 @@
     test/goldens/getqq_no_operators.golden
     test/goldens/getqq_ops_after_list.golden
     test/goldens/getqq_ops_after_tuple.golden
-    test/goldens/integration/ghc-8.10/getqq_missing_key.golden
-    test/goldens/integration/ghc-9.0/getqq_missing_key.golden
-    test/goldens/integration/ghc-9.2/getqq_missing_key.golden
-    test/goldens/integration/ghc-9.4/getqq_missing_key.golden
+    test/goldens/ghc/9.4/getqq_missing_key.golden
+    test/goldens/ghc/9.6/getqq_missing_key.golden
+    test/goldens/ghc/9.8/getqq_missing_key.golden
+    test/goldens/ghc/9.9/getqq_missing_key.golden
     test/goldens/README_Quickstart.golden
     test/goldens/schemaqq_key_with_invalid_character.golden
     test/goldens/schemaqq_key_with_trailing_escape.golden
@@ -55,10 +55,6 @@
   type: git
   location: https://github.com/brandonchinn178/aeson-schemas
 
-flag run-integration-tests
-  manual: True
-  default: False
-
 library
   exposed-modules:
       Data.Aeson.Schema
@@ -81,21 +77,17 @@
       Data.Aeson.Schema.TH.Utils
   hs-source-dirs:
       src
-  ghc-options: -Wall
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances -Wunused-packages
   build-depends:
-      aeson >=1.1.2.0 && <3
-    , base >=4.14 && <5
-    , first-class-families >=0.3.0.0 && <0.9
-    , hashable >=1.2.7.0 && <1.5
-    , megaparsec >=7 && <10
-    , template-haskell >=2.16 && <2.21
-    , text >=1.2.2.2 && <2.1
-    , unordered-containers >=0.2.8.0 && <0.3
+      aeson <3
+    , base >=4.17 && <5
+    , first-class-families <0.9
+    , hashable <1.5
+    , megaparsec <10
+    , template-haskell <2.22
+    , text <2.2
+    , unordered-containers <0.3
   default-language: Haskell2010
-  if impl(ghc >= 8.0)
-    ghc-options: -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
-  if impl(ghc < 8.8)
-    ghc-options: -Wnoncanonical-monadfail-instances
 
 test-suite aeson-schemas-test
   type: exitcode-stdio-1.0
@@ -124,35 +116,32 @@
       Paths_aeson_schemas
   hs-source-dirs:
       test
-  ghc-options: -Wall
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances -Wunused-packages
   build-depends:
       QuickCheck
     , aeson
-    , aeson-qq
+    , aeson-qq >=0.8.4
     , aeson-schemas
     , base
     , deepseq
-    , directory
     , filepath
+    , hint
     , interpolate
     , process
     , raw-strings-qq
     , tasty
     , tasty-golden
     , tasty-hunit
-    , tasty-quickcheck
+    , tasty-quickcheck >=0.8.1
     , template-haskell
     , temporary
     , text
     , th-orphans
     , th-test-utils
   default-language: Haskell2010
-  if impl(ghc >= 8.0)
-    ghc-options: -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
-  if impl(ghc < 8.8)
-    ghc-options: -Wnoncanonical-monadfail-instances
-  if flag(run-integration-tests)
-    cpp-options: -DRUN_INTEGRATION_TESTS
+  if impl(ghc < 9.2)
+    build-depends:
+        hint <0.9.0.6
 
 benchmark aeson-schemas-bench
   type: exitcode-stdio-1.0
@@ -169,7 +158,7 @@
       Paths_aeson_schemas
   hs-source-dirs:
       bench
-  ghc-options: -Wall
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances -Wunused-packages
   build-depends:
       aeson
     , aeson-schemas
@@ -179,7 +168,3 @@
     , template-haskell
     , th-test-utils
   default-language: Haskell2010
-  if impl(ghc >= 8.0)
-    ghc-options: -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
-  if impl(ghc < 8.8)
-    ghc-options: -Wnoncanonical-monadfail-instances
diff --git a/bench/Benchmarks/Data/Objects.hs b/bench/Benchmarks/Data/Objects.hs
--- a/bench/Benchmarks/Data/Objects.hs
+++ b/bench/Benchmarks/Data/Objects.hs
@@ -7,6 +7,7 @@
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 
 module Benchmarks.Data.Objects where
 
diff --git a/src/Data/Aeson/Schema/TH/Get.hs b/src/Data/Aeson/Schema/TH/Get.hs
--- a/src/Data/Aeson/Schema/TH/Get.hs
+++ b/src/Data/Aeson/Schema/TH/Get.hs
@@ -127,9 +127,6 @@
 
 {- Runtime helpers -}
 
-{- HLINT ignore fromJust "Redundant bracket" -}
--- https://github.com/ndmitchell/hlint/issues/1503
-
 -- | fromJust with helpful error message
 fromJust :: (HasCallStack) => String -> Maybe a -> a
 fromJust expr = Maybe.fromMaybe (error errMsg)
diff --git a/test/TestUtils.hs b/test/TestUtils.hs
--- a/test/TestUtils.hs
+++ b/test/TestUtils.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
@@ -20,7 +21,7 @@
   testGolden,
   testGoldenIO,
   testParseError,
-  testIntegration,
+  ghcGoldenDir,
 ) where
 
 import Data.Aeson (FromJSON (..), Value, eitherDecode)
@@ -35,10 +36,7 @@
 import Data.Typeable (Typeable, typeRep)
 import Language.Haskell.TH (ExpQ)
 import Language.Haskell.TH.Quote (QuasiQuoter (..))
-import System.Directory (findExecutable)
 import System.FilePath ((</>))
-import System.IO.Unsafe (unsafePerformIO)
-import System.Process (readProcess)
 import Test.Tasty (TestTree)
 import Test.Tasty.Golden (goldenVsString)
 import Test.Tasty.Golden.Advanced (goldenTest)
@@ -111,27 +109,13 @@
           else Just $ "Test output was different from '" ++ goldenFile ++ "'. It was:\n" ++ Text.unpack actual
     update = Text.writeFile goldenFile
 
--- | A golden test for integration tests calling GHC.
-testIntegration :: String -> FilePath -> (FilePath -> IO String) -> TestTree
-testIntegration name fp runTest =
-  testGoldenIO name ("integration" </> ("ghc-" ++ ghcVersionShort) </> fp) (runTest ghcExe)
+-- | The directory to put GHC version-specific golden files.
+ghcGoldenDir :: FilePath
+ghcGoldenDir = "ghc" </> ghcVersion
   where
-    ghcVersionShort =
-      case map Text.unpack . Text.splitOn "." . Text.pack $ ghcVersion of
-        [x, y, _] -> x ++ "." ++ y
-        _ -> error $ "Could not parse GHC version: " ++ ghcVersion
-
-{-# NOINLINE ghcExe #-}
-ghcExe :: FilePath
-ghcExe =
-  unsafePerformIO $
-    findExecutable "ghc" >>= \case
-      Just fp -> pure fp
-      Nothing -> error "Could not find GHC executable"
-
-{-# NOINLINE ghcVersion #-}
-ghcVersion :: String
-ghcVersion =
-  unsafePerformIO $
-    Text.unpack . Text.strip . Text.pack
-      <$> readProcess ghcExe ["--numeric-version"] ""
+    ghcVersion =
+      Text.unpack
+        . Text.intercalate "."
+        . take 2
+        . Text.splitOn "."
+        $ __GLASGOW_HASKELL_FULL_VERSION__
diff --git a/test/TestUtils/DeepSeq.hs b/test/TestUtils/DeepSeq.hs
--- a/test/TestUtils/DeepSeq.hs
+++ b/test/TestUtils/DeepSeq.hs
@@ -62,6 +62,10 @@
 instance NFData TyVarBndr
 #endif
 
+#if MIN_VERSION_template_haskell(2,20,0) && __GLASGOW_HASKELL__ >= 907
+instance NFData BndrVis
+#endif
+
 instance NFData Bytes
 
 instance NFData (ForeignPtr a) where
diff --git a/test/Tests/GetQQ.hs b/test/Tests/GetQQ.hs
--- a/test/Tests/GetQQ.hs
+++ b/test/Tests/GetQQ.hs
@@ -13,11 +13,13 @@
 module Tests.GetQQ where
 
 import Control.DeepSeq (deepseq)
-import Control.Exception (SomeException, try)
+import Control.Exception (SomeException, displayException, try)
 import Data.Aeson (FromJSON (..), ToJSON (..), withText)
 import Data.Aeson.QQ (aesonQQ)
 import Data.Text (Text)
 import qualified Data.Text as Text
+import qualified Language.Haskell.Interpreter as Hint
+import System.FilePath ((</>))
 import Test.Tasty
 import Test.Tasty.HUnit
 import Test.Tasty.QuickCheck
@@ -25,12 +27,7 @@
 import Data.Aeson.Schema (Object, schema)
 import Data.Aeson.Schema.TH (mkEnum)
 import Data.Aeson.Schema.Utils.Sum (SumType (..))
-import System.Directory (copyFile, createDirectoryIfMissing, withCurrentDirectory)
-import System.Exit (ExitCode (..))
-import System.FilePath (takeDirectory, (</>))
-import System.IO.Temp (withSystemTempDirectory)
-import System.Process (readProcessWithExitCode)
-import TestUtils (parseObject, testIntegration, testParseError)
+import TestUtils (ghcGoldenDir, parseObject, testGoldenIO, testParseError)
 import Tests.GetQQ.TH
 
 mkEnum "Greeting" ["HELLO", "GOODBYE"]
@@ -259,7 +256,9 @@
     assertError msg x =
       try @SomeException (x `deepseq` pure ()) >>= \case
         Right _ -> error "Unexpectedly succeeded"
-        Left e -> (head . lines . show) e @?= msg
+        Left e
+          | line : _ <- (lines . show) e -> line @?= msg
+          | otherwise -> error "Exception had no message"
 
 testListExpressions :: TestTree
 testListExpressions =
@@ -393,37 +392,19 @@
         [getErr| o.[a,b].foo |]
     ]
 
-{- HLINT ignore testCompileTimeErrors "Evaluate" -}
 testCompileTimeErrors :: TestTree
 testCompileTimeErrors =
-  testGroup "Compile-time errors" . map mkIntegrationTest $
-    [ testIntegration "Key not in schema" "getqq_missing_key.golden" $ \ghcExe ->
-        getCompileError ghcExe "GetMissingKey.hs"
+  testGroup
+    "Compile-time errors"
+    [ testGoldenIO "Key not in schema" (ghcGoldenDir </> "getqq_missing_key.golden") $
+        getCompileError (testDir </> "GetMissingKey.hs")
     ]
   where
     testDir = "test/wont-compile/"
-    getCompileError ghcExe file =
-      withSystemTempDirectory "aeson-schemas-integration-tests" $ \tmpdir -> do
-        let fp = tmpdir </> testDir </> file
-        createDirectoryIfMissing True (takeDirectory fp)
-        copyFile (testDir </> file) fp
-        withCurrentDirectory tmpdir $
-          readProcessWithExitCode ghcExe [fp] "" >>= \case
-            (ExitFailure{}, _, stderr) ->
-              return . Text.unpack . Text.replace (Text.pack tmpdir) "" . Text.pack $ stderr
-            (ExitSuccess, stdout, stderr) ->
-              error . unlines $
-                [ "Compilation unexpectedly succeeded"
-                , stdout
-                , stderr
-                ]
-
-mkIntegrationTest :: TestTree -> TestTree
-#ifdef RUN_INTEGRATION_TESTS
-mkIntegrationTest = id
-#else
-mkIntegrationTest _ = testGroup "integration test" []
-#endif
+    getCompileError fp =
+      Hint.runInterpreter (Hint.loadModules [fp]) >>= \case
+        Left e -> pure $ displayException e
+        Right _ -> error "Compilation unexpectedly succeeded"
 
 {- Helpers -}
 
diff --git a/test/goldens/ghc/9.4/getqq_missing_key.golden b/test/goldens/ghc/9.4/getqq_missing_key.golden
new file mode 100644
--- /dev/null
+++ b/test/goldens/ghc/9.4/getqq_missing_key.golden
@@ -0,0 +1,18 @@
+test/wont-compile/GetMissingKey.hs:17:15: error:
+    • Key 'missing' does not exist in the following schema:
+      '[ '( 'Data.Aeson.Schema.Key.NormalKey "foo",
+            'Data.Aeson.Schema.Type.SchemaScalar Bool)]
+    • In the second argument of ‘(.)’, namely
+        ‘Data.Aeson.Schema.Internal.getKey
+           (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing")’
+      In the expression:
+        (id
+           . Data.Aeson.Schema.Internal.getKey
+               (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing"))
+          o
+      In an equation for ‘result’:
+          result
+            = ((id
+                  . Data.Aeson.Schema.Internal.getKey
+                      (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing"))
+                 o)
diff --git a/test/goldens/ghc/9.6/getqq_missing_key.golden b/test/goldens/ghc/9.6/getqq_missing_key.golden
new file mode 100644
--- /dev/null
+++ b/test/goldens/ghc/9.6/getqq_missing_key.golden
@@ -0,0 +1,18 @@
+test/wont-compile/GetMissingKey.hs:17:15: error: [GHC-64725]
+    • Key 'missing' does not exist in the following schema:
+      '[ '(Data.Aeson.Schema.Key.NormalKey "foo",
+           Data.Aeson.Schema.Type.SchemaScalar Bool)]
+    • In the second argument of ‘(.)’, namely
+        ‘Data.Aeson.Schema.Internal.getKey
+           (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing")’
+      In the expression:
+        (id
+           . Data.Aeson.Schema.Internal.getKey
+               (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing"))
+          o
+      In an equation for ‘result’:
+          result
+            = ((id
+                  . Data.Aeson.Schema.Internal.getKey
+                      (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing"))
+                 o)
diff --git a/test/goldens/ghc/9.8/getqq_missing_key.golden b/test/goldens/ghc/9.8/getqq_missing_key.golden
new file mode 100644
--- /dev/null
+++ b/test/goldens/ghc/9.8/getqq_missing_key.golden
@@ -0,0 +1,18 @@
+test/wont-compile/GetMissingKey.hs:17:15: error: [GHC-64725]
+    • Key 'missing' does not exist in the following schema:
+      '[ '(Data.Aeson.Schema.Key.NormalKey "foo",
+           Data.Aeson.Schema.Type.SchemaScalar Bool)]
+    • In the second argument of ‘(.)’, namely
+        ‘Data.Aeson.Schema.Internal.getKey
+           (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing")’
+      In the expression:
+        (id
+           . Data.Aeson.Schema.Internal.getKey
+               (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing"))
+          o
+      In an equation for ‘result’:
+          result
+            = ((id
+                  . Data.Aeson.Schema.Internal.getKey
+                      (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing"))
+                 o)
diff --git a/test/goldens/ghc/9.9/getqq_missing_key.golden b/test/goldens/ghc/9.9/getqq_missing_key.golden
new file mode 100644
--- /dev/null
+++ b/test/goldens/ghc/9.9/getqq_missing_key.golden
@@ -0,0 +1,18 @@
+test/wont-compile/GetMissingKey.hs:17:15: error: [GHC-64725]
+    • Key 'missing' does not exist in the following schema:
+      '[ '(Data.Aeson.Schema.Key.NormalKey "foo",
+           Data.Aeson.Schema.Type.SchemaScalar Bool)]
+    • In the second argument of ‘(.)’, namely
+        ‘Data.Aeson.Schema.Internal.getKey
+           (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing")’
+      In the expression:
+        (id
+           . Data.Aeson.Schema.Internal.getKey
+               (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing"))
+          o
+      In an equation for ‘result’:
+          result
+            = ((id
+                  . Data.Aeson.Schema.Internal.getKey
+                      (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing"))
+                 o)
diff --git a/test/goldens/integration/ghc-8.10/getqq_missing_key.golden b/test/goldens/integration/ghc-8.10/getqq_missing_key.golden
deleted file mode 100644
--- a/test/goldens/integration/ghc-8.10/getqq_missing_key.golden
+++ /dev/null
@@ -1,10 +0,0 @@
-
-/test/wont-compile/GetMissingKey.hs:17:1: error:
-    • Key 'missing' does not exist in the following schema:
-      '[ '( 'Data.Aeson.Schema.Key.NormalKey "foo",
-            'Data.Aeson.Schema.Type.SchemaScalar Bool)]
-    • When checking the inferred type
-        result :: Data.Aeson.Schema.Internal.SchemaResult (TypeError ...)
-   |
-17 | result = [get| o.missing |]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/test/goldens/integration/ghc-9.0/getqq_missing_key.golden b/test/goldens/integration/ghc-9.0/getqq_missing_key.golden
deleted file mode 100644
--- a/test/goldens/integration/ghc-9.0/getqq_missing_key.golden
+++ /dev/null
@@ -1,10 +0,0 @@
-
-/test/wont-compile/GetMissingKey.hs:17:1: error:
-    • Key 'missing' does not exist in the following schema:
-      '[ '( 'Data.Aeson.Schema.Key.NormalKey "foo",
-            'Data.Aeson.Schema.Type.SchemaScalar Bool)]
-    • When checking the inferred type
-        result :: Data.Aeson.Schema.Internal.SchemaResult (TypeError ...)
-   |
-17 | result = [get| o.missing |]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/test/goldens/integration/ghc-9.2/getqq_missing_key.golden b/test/goldens/integration/ghc-9.2/getqq_missing_key.golden
deleted file mode 100644
--- a/test/goldens/integration/ghc-9.2/getqq_missing_key.golden
+++ /dev/null
@@ -1,10 +0,0 @@
-
-/test/wont-compile/GetMissingKey.hs:17:1: error:
-    • Key 'missing' does not exist in the following schema:
-      '[ '( 'Data.Aeson.Schema.Key.NormalKey "foo",
-            'Data.Aeson.Schema.Type.SchemaScalar Bool)]
-    • When checking the inferred type
-        result :: Data.Aeson.Schema.Internal.SchemaResult (TypeError ...)
-   |
-17 | result = [get| o.missing |]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/test/goldens/integration/ghc-9.4/getqq_missing_key.golden b/test/goldens/integration/ghc-9.4/getqq_missing_key.golden
deleted file mode 100644
--- a/test/goldens/integration/ghc-9.4/getqq_missing_key.golden
+++ /dev/null
@@ -1,44 +0,0 @@
-
-/test/wont-compile/GetMissingKey.hs:17:15: error:
-    • Key 'missing' does not exist in the following schema:
-      '[ '( 'Data.Aeson.Schema.Key.NormalKey "foo",
-            'Data.Aeson.Schema.Type.SchemaScalar Bool)]
-    • In the second argument of ‘(.)’, namely
-        ‘Data.Aeson.Schema.Internal.getKey
-           (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing")’
-      In the expression:
-        (id
-           . Data.Aeson.Schema.Internal.getKey
-               (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing"))
-          o
-      In an equation for ‘result’:
-          result
-            = ((id
-                  . Data.Aeson.Schema.Internal.getKey
-                      (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing"))
-                 o)
-   |
-17 | result = [get| o.missing |]
-   |               ^^^^^^^^^^^^^
-
-/test/wont-compile/GetMissingKey.hs:17:15: error:
-    • Key 'missing' does not exist in the following schema:
-      '[ '( 'Data.Aeson.Schema.Key.NormalKey "foo",
-            'Data.Aeson.Schema.Type.SchemaScalar Bool)]
-    • In the second argument of ‘(.)’, namely
-        ‘Data.Aeson.Schema.Internal.getKey
-           (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing")’
-      In the expression:
-        (id
-           . Data.Aeson.Schema.Internal.getKey
-               (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing"))
-          o
-      In an equation for ‘result’:
-          result
-            = ((id
-                  . Data.Aeson.Schema.Internal.getKey
-                      (Data.Proxy.Proxy :: Data.Proxy.Proxy "missing"))
-                 o)
-   |
-17 | result = [get| o.missing |]
-   |               ^^^^^^^^^^^^^
