diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## Stache 2.2.1
+
+* Works with GHC 9.0.1, dropped support for GHC 8.6.x and older.
+
 ## Stache 2.2.0
 
 * Added the executable program.
diff --git a/Text/Mustache/Parser.hs b/Text/Mustache/Parser.hs
--- a/Text/Mustache/Parser.hs
+++ b/Text/Mustache/Parser.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 -- |
@@ -29,10 +28,6 @@
 import Text.Megaparsec.Char
 import qualified Text.Megaparsec.Char.Lexer as L
 import Text.Mustache.Type
-
-#if !MIN_VERSION_base(4,13,0)
-import Data.Semigroup ((<>))
-#endif
 
 ----------------------------------------------------------------------------
 -- Parser
diff --git a/Text/Mustache/Render.hs b/Text/Mustache/Render.hs
--- a/Text/Mustache/Render.hs
+++ b/Text/Mustache/Render.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 -- |
@@ -36,10 +35,6 @@
 import qualified Data.Vector as V
 import Text.Megaparsec.Pos (Pos, mkPos, unPos)
 import Text.Mustache.Type
-
-#if !MIN_VERSION_base(4,13,0)
-import Data.Semigroup ((<>))
-#endif
 
 ----------------------------------------------------------------------------
 -- The rendering monad
diff --git a/Text/Mustache/Type.hs b/Text/Mustache/Type.hs
--- a/Text/Mustache/Type.hs
+++ b/Text/Mustache/Type.hs
@@ -67,7 +67,9 @@
 instance TH.Lift Template where
   lift = liftData
 
-#if MIN_VERSION_template_haskell(2,16,0)
+#if MIN_VERSION_template_haskell(2,17,0)
+  liftTyped = TH.Code . TH.unsafeTExpCoerce . TH.lift
+#elif MIN_VERSION_template_haskell(2,16,0)
   liftTyped = TH.unsafeTExpCoerce . TH.lift
 #endif
 
@@ -91,7 +93,9 @@
 instance TH.Lift Node where
   lift = liftData
 
-#if MIN_VERSION_template_haskell(2,16,0)
+#if MIN_VERSION_template_haskell(2,17,0)
+  liftTyped = TH.Code . TH.unsafeTExpCoerce . TH.lift
+#elif MIN_VERSION_template_haskell(2,16,0)
   liftTyped = TH.unsafeTExpCoerce . TH.lift
 #endif
 
@@ -111,7 +115,9 @@
 instance TH.Lift Key where
   lift = liftData
 
-#if MIN_VERSION_template_haskell(2,16,0)
+#if MIN_VERSION_template_haskell(2,17,0)
+  liftTyped = TH.Code . TH.unsafeTExpCoerce . TH.lift
+#elif MIN_VERSION_template_haskell(2,16,0)
   liftTyped = TH.unsafeTExpCoerce . TH.lift
 #endif
 
@@ -137,7 +143,9 @@
 instance TH.Lift PName where
   lift = liftData
 
-#if MIN_VERSION_template_haskell(2,16,0)
+#if MIN_VERSION_template_haskell(2,17,0)
+  liftTyped = TH.Code . TH.unsafeTExpCoerce . TH.lift
+#elif MIN_VERSION_template_haskell(2,16,0)
   liftTyped = TH.unsafeTExpCoerce . TH.lift
 #endif
 
@@ -179,8 +187,20 @@
 ----------------------------------------------------------------------------
 -- TH lifting helpers
 
-liftData :: Data a => a -> TH.Q TH.Exp
+liftData
+
+#if MIN_VERSION_template_haskell(2,17,0)
+  :: (Data a, TH.Quote m) => a -> m TH.Exp
+#else
+  :: Data a => a -> TH.Q TH.Exp
+#endif
 liftData = TH.dataToExpQ (fmap liftText . cast)
 
-liftText :: Text -> TH.Q TH.Exp
+liftText
+
+#if MIN_VERSION_template_haskell(2,17,0)
+  :: TH.Quote m => Text -> m TH.Exp
+#else
+  :: Text -> TH.Q TH.Exp
+#endif
 liftText t = TH.AppE (TH.VarE 'T.pack) <$> TH.lift (T.unpack t)
diff --git a/stache.cabal b/stache.cabal
--- a/stache.cabal
+++ b/stache.cabal
@@ -1,11 +1,11 @@
 cabal-version:   1.18
 name:            stache
-version:         2.2.0
+version:         2.2.1
 license:         BSD3
 license-file:    LICENSE.md
 maintainer:      Mark Karpov <markkarpov92@gmail.com>
 author:          Mark Karpov <markkarpov92@gmail.com>
-tested-with:     ghc ==8.6.5 ghc ==8.8.3 ghc ==8.10.1
+tested-with:     ghc ==8.8.4 ghc ==8.10.4 ghc ==9.0.1
 homepage:        https://github.com/stackbuilders/stache
 bug-reports:     https://github.com/stackbuilders/stache/issues
 synopsis:        Mustache templates for Haskell
@@ -42,15 +42,15 @@
     default-language: Haskell2010
     build-depends:
         aeson >=0.11 && <1.6,
-        base >=4.12 && <5.0,
-        bytestring >=0.10 && <0.11,
+        base >=4.13 && <5.0,
+        bytestring >=0.10 && <0.12,
         containers >=0.5 && <0.7,
         deepseq >=1.4 && <1.5,
         directory >=1.2 && <1.4,
         filepath >=1.2 && <1.5,
-        megaparsec >=7.0 && <9.0,
+        megaparsec >=7.0 && <10.0,
         mtl >=2.1 && <3.0,
-        template-haskell >=2.11 && <2.17,
+        template-haskell >=2.11 && <2.18,
         text >=1.2 && <1.3,
         unordered-containers >=0.2.5 && <0.3,
         vector >=0.11 && <0.13
@@ -73,9 +73,9 @@
     default-language: Haskell2010
     build-depends:
         aeson >=0.11 && <1.6,
-        base >=4.12 && <5.0,
+        base >=4.13 && <5.0,
         gitrev >=1.3 && <1.4,
-        optparse-applicative >=0.14 && <0.16,
+        optparse-applicative >=0.14 && <0.17,
         stache >=2.0 && <3.0,
         text >=0.2 && <1.3,
         unordered-containers >=0.2.5 && <0.3,
@@ -104,13 +104,13 @@
     default-language: Haskell2010
     build-depends:
         aeson >=0.11 && <1.6,
-        base >=4.12 && <5.0,
+        base >=4.13 && <5.0,
         containers >=0.5 && <0.7,
         hspec >=2.0 && <3.0,
         hspec-megaparsec >=2.0 && <3.0,
-        megaparsec >=7.0 && <9.0,
+        megaparsec >=7.0 && <10.0,
         stache -any,
-        template-haskell >=2.11 && <2.17,
+        template-haskell >=2.11 && <2.18,
         text >=1.2 && <1.3
 
     if flag(dev)
@@ -126,12 +126,12 @@
     default-language: Haskell2010
     build-depends:
         aeson >=0.11 && <1.6,
-        base >=4.12 && <5.0,
-        bytestring >=0.10 && <0.11,
+        base >=4.13 && <5.0,
+        bytestring >=0.10 && <0.12,
         containers >=0.5 && <0.7,
         file-embed -any,
         hspec >=2.0 && <3.0,
-        megaparsec >=7.0 && <9.0,
+        megaparsec >=7.0 && <10.0,
         stache -any,
         text >=1.2 && <1.3,
         yaml >=0.8 && <0.12
@@ -149,10 +149,10 @@
     default-language: Haskell2010
     build-depends:
         aeson >=0.11 && <1.6,
-        base >=4.12 && <5.0,
+        base >=4.13 && <5.0,
         criterion >=0.6.2.1 && <1.6,
         deepseq >=1.4 && <1.5,
-        megaparsec >=7.0 && <9.0,
+        megaparsec >=7.0 && <10.0,
         stache -any,
         text >=1.2 && <1.3
 
diff --git a/tests/Text/Mustache/Compile/THSpec.hs b/tests/Text/Mustache/Compile/THSpec.hs
--- a/tests/Text/Mustache/Compile/THSpec.hs
+++ b/tests/Text/Mustache/Compile/THSpec.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
 {-# LANGUAGE TemplateHaskell #-}
@@ -13,10 +12,6 @@
 import Test.Hspec
 import qualified Text.Mustache.Compile.TH as TH
 import Text.Mustache.Type
-
-#if !MIN_VERSION_base(4,13,0)
-import Data.Semigroup ((<>))
-#endif
 
 main :: IO ()
 main = hspec spec
diff --git a/tests/Text/Mustache/ParserSpec.hs b/tests/Text/Mustache/ParserSpec.hs
--- a/tests/Text/Mustache/ParserSpec.hs
+++ b/tests/Text/Mustache/ParserSpec.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Text.Mustache.ParserSpec
@@ -12,10 +11,6 @@
 import Text.Megaparsec
 import Text.Mustache.Parser
 import Text.Mustache.Type
-
-#if !MIN_VERSION_base(4,13,0)
-import Data.Semigroup ((<>))
-#endif
 
 main :: IO ()
 main = hspec spec
diff --git a/tests/Text/Mustache/TypeSpec.hs b/tests/Text/Mustache/TypeSpec.hs
--- a/tests/Text/Mustache/TypeSpec.hs
+++ b/tests/Text/Mustache/TypeSpec.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Text.Mustache.TypeSpec
@@ -11,10 +10,6 @@
 import Test.Hspec
 import Text.Mustache.Type
 
-#if !MIN_VERSION_base(4,13,0)
-import Data.Semigroup ((<>))
-#endif
-
 main :: IO ()
 main = hspec spec
 
@@ -22,25 +17,25 @@
 spec = do
   describe "Template instances" $
     context "the Semigroup instance" $ do
-        it "the resulting template inherits focus of the left one" $
-          templateActual (templateA <> templateB)
-            `shouldBe` templateActual templateA
-        it "the resulting template merges caches with left bias" $
-          templateCache (templateA <> templateB)
-            `shouldBe` M.fromList
-              [ ("c", [TextBlock "foo"]),
-                ("d", [TextBlock "bar"]),
-                ("e", [TextBlock "baz"])
-              ]
+      it "the resulting template inherits focus of the left one" $
+        templateActual (templateA <> templateB)
+          `shouldBe` templateActual templateA
+      it "the resulting template merges caches with left bias" $
+        templateCache (templateA <> templateB)
+          `shouldBe` M.fromList
+            [ ("c", [TextBlock "foo"]),
+              ("d", [TextBlock "bar"]),
+              ("e", [TextBlock "baz"])
+            ]
   describe "showKey" $ do
     context "when the key has no elements in it" $
       it "is rendered correctly" $
         showKey (Key []) `shouldBe` "<implicit>"
     context "when the key has some elements" $
       it "is rendered correctly" $ do
-          showKey (Key ["boo"]) `shouldBe` "boo"
-          showKey (Key ["foo", "bar"]) `shouldBe` "foo.bar"
-          showKey (Key ["baz", "baz", "quux"]) `shouldBe` "baz.baz.quux"
+        showKey (Key ["boo"]) `shouldBe` "boo"
+        showKey (Key ["foo", "bar"]) `shouldBe` "foo.bar"
+        showKey (Key ["baz", "baz", "quux"]) `shouldBe` "baz.baz.quux"
   describe "displayMustacheWarning" $ do
     it "renders “not found” warning correctly" $
       displayMustacheWarning (MustacheVariableNotFound (Key ["foo"]))
