diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,10 @@
 `fused-effects-th` uses [PVP Versioning][1].
 The changelog is available [on GitHub][2].
 
+## 0.1.0.3
+
+* GHC 9 support.
+
 ## 0.1.0.2
 
 * Fix a bug where typeclass constraints on GADT constructors were being ignored.
diff --git a/fused-effects-th.cabal b/fused-effects-th.cabal
--- a/fused-effects-th.cabal
+++ b/fused-effects-th.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.4
 name:                fused-effects-th
-version:             0.1.0.2
+version:             0.1.0.3
 synopsis:            Template Haskell helpers for fused-effects.
 description:         This package provides Template Haskell splices that wrap the smart constructors needed for declaring new effects when using the fused-effects effect system.
 homepage:            https://github.com/fused-effects/fused-effects-th
@@ -17,15 +17,16 @@
 tested-with:         GHC == 8.6.5
                      GHC == 8.8.3
                      GHC == 8.10.2
+                     GHC == 9.0.1
 
 source-repository head
   type:                git
   location:            https://github.com/fused-effects/fused-effects-th.git
 
 common common-options
-  build-depends:       base >= 4.12 && < 4.15
+  build-depends:       base >= 4.12 && < 4.16
                      , fused-effects ^>= 1.1
-                     , template-haskell >= 2.12 && < 2.17
+                     , template-haskell >= 2.12 && < 2.18
 
   ghc-options:         -Wall
                        -Wcompat
@@ -55,7 +56,7 @@
   hs-source-dirs:      test
   main-is:             Spec.hs
   build-depends:       fused-effects-th
-                     , tasty ^>= 1.3
+                     , tasty >= 1.3 && <1.5
                      , tasty-hunit >= 0.10
   ghc-options:         -threaded
                        -rtsopts
diff --git a/src/Control/Effect/TH.hs b/src/Control/Effect/TH.hs
--- a/src/Control/Effect/TH.hs
+++ b/src/Control/Effect/TH.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE QuasiQuotes #-}
 {-# LANGUAGE RecordWildCards #-}
@@ -24,11 +25,35 @@
     forallConstructor :: TH.Con
   }
 
+-- Hideous hacks to deal with kindedness changes in newer TH versions.
+#if MIN_VERSION_template_haskell(2,17,0)
+type TyVarBinder = TH.TyVarBndrSpec
+
+makeTV :: TH.Name -> TyVarBinder
+makeTV n = TH.PlainTV n TH.inferredSpec
+
+tvName :: TyVarBinder -> TH.Name
+tvName = \case
+  TH.PlainTV n _ -> n
+  TH.KindedTV n _ _ -> n
+#else
+type TyVarBinder = TH.TyVarBndr
+
+makeTV :: TH.Name -> TyVarBinder
+makeTV = TH.plainTV
+
+tvName :: TyVarBinder -> TH.Name
+tvName = \case
+  TH.PlainTV n -> n
+  TH.KindedTV n _ -> n
+#endif
+
+
 data PerDecl = PerDecl
   { ctorArgs :: [TH.TypeQ],
     ctorConstraints :: [TH.TypeQ],
     ctorName :: TH.Name,
-    ctorTyVars :: [TH.TyVarBndr],
+    ctorTyVars :: [TyVarBinder],
     functionName :: TH.Name,
     gadtReturnType :: TH.TypeQ,
     perEffect :: PerEffect
@@ -126,10 +151,7 @@
 makeSignature PerDecl {perEffect = PerEffect {..}, ..} =
   let sigVar = mkName "sig"
       (rest, monadTV) = (init ctorTyVars, last ctorTyVars)
-      getTyVar =
-        varT . \case
-          TH.PlainTV n -> n
-          TH.KindedTV n _ -> n
+      getTyVar = varT . tvName
       monadName = getTyVar monadTV
       -- Build the parameter to Has by consulting the number of required type parameters.
       invocation = foldl' appT effectType (fmap getTyVar (take (effectTyVarCount - 2) rest))
@@ -138,4 +160,4 @@
       foldedSig = foldr (\a b -> arrowT `appT` a `appT` b) (monadName `appT` gadtReturnType) ctorArgs
       -- Glue together the Has and the per-constructor constraints.
       allConstraints = TH.cxt (hasConstraint : ctorConstraints)
-   in TH.sigD functionName (TH.forallT (rest ++ [monadTV, TH.plainTV sigVar]) allConstraints foldedSig)
+   in TH.sigD functionName (TH.forallT (rest ++ [monadTV, makeTV sigVar]) allConstraints foldedSig)
