diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # Changelog for pantry
 
+## v0.5.4
+
+* Support aeson 2
+
 ## v0.5.3
 
 * improve and expose `fetchRepos`/`fetchReposRaw`
diff --git a/pantry.cabal b/pantry.cabal
--- a/pantry.cabal
+++ b/pantry.cabal
@@ -3,11 +3,9 @@
 -- This file has been generated from package.yaml by hpack version 0.34.4.
 --
 -- see: https://github.com/sol/hpack
---
--- hash: 290314cf42f0f169e5cb395c4b35e867438c4e2652df972ec59c548dc39f1b6d
 
 name:           pantry
-version:        0.5.3
+version:        0.5.4
 synopsis:       Content addressable Haskell package management
 description:    Please see the README on Github at <https://github.com/commercialhaskell/pantry#readme>
 category:       Development
diff --git a/src/Pantry/Internal/AesonExtended.hs b/src/Pantry/Internal/AesonExtended.hs
--- a/src/Pantry/Internal/AesonExtended.hs
+++ b/src/Pantry/Internal/AesonExtended.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE DeriveGeneric #-}
@@ -35,7 +36,6 @@
 import Data.Aeson as Export hiding ((.:), (.:?))
 import qualified Data.Aeson as A
 import Data.Aeson.Types hiding ((.:), (.:?))
-import qualified Data.HashMap.Strict as HashMap
 import qualified Data.Set as Set
 import Data.Text (unpack)
 import qualified Data.Text as T
@@ -43,14 +43,33 @@
 import RIO
 import RIO.PrettyPrint.StylesUpdate (StylesUpdate)
 
+#if MIN_VERSION_aeson(2, 0, 0)
+import qualified Data.Aeson.Key
+import qualified Data.Aeson.KeyMap as HashMap
+
+keyToText :: Data.Aeson.Key.Key -> Text
+keyToText = Data.Aeson.Key.toText
+
+textToKey :: Text -> Data.Aeson.Key.Key
+textToKey = Data.Aeson.Key.fromText
+#else
+import qualified Data.HashMap.Strict as HashMap
+
+keyToText :: Text -> Text
+keyToText = id
+
+textToKey :: Text -> Text
+textToKey = id
+#endif
+
 -- | Extends @.:@ warning to include field name.
 (.:) :: FromJSON a => Object -> Text -> Parser a
-(.:) o p = modifyFailure (("failed to parse field '" <> unpack p <> "': ") <>) (o A..: p)
+(.:) o p = modifyFailure (("failed to parse field '" <> unpack p <> "': ") <>) (o A..: textToKey p)
 {-# INLINE (.:) #-}
 
 -- | Extends @.:?@ warning to include field name.
 (.:?) :: FromJSON a => Object -> Text -> Parser (Maybe a)
-(.:?) o p = modifyFailure (("failed to parse field '" <> unpack p <> "': ") <>) (o A..:? p)
+(.:?) o p = modifyFailure (("failed to parse field '" <> unpack p <> "': ") <>) (o A..:? textToKey p)
 {-# INLINE (.:?) #-}
 
 -- | 'WarningParser' version of @.:@.
@@ -74,7 +93,7 @@
             fmap (, a) (fmap fst p .!= d)
 
 presentCount :: Object -> [Text] -> Int
-presentCount o ss = length . filter (\x -> HashMap.member x o) $ ss
+presentCount o ss = length . filter (\x -> HashMap.member (textToKey x) o) $ ss
 
 -- | Synonym version of @..:@.
 (...:) :: FromJSON a => Object -> [Text] -> WarningParser a
@@ -121,7 +140,7 @@
             let unrecognizedFields =
                     Set.toList
                         (Set.difference
-                             (Set.fromList (HashMap.keys obj))
+                             (Set.fromList (map keyToText (HashMap.keys obj)))
                              (wpmExpectedFields w))
             return
                 (WithJSONWarnings a
diff --git a/src/Pantry/Repo.hs b/src/Pantry/Repo.hs
--- a/src/Pantry/Repo.hs
+++ b/src/Pantry/Repo.hs
@@ -81,7 +81,7 @@
       :: RIO env Package
       -> RIO env Package
     withCache inner = do
-      mtid <- withStorage (loadRepoCache repo (repoSubdir repo))
+      mtid <- withStorage (loadRepoCache repo)
       case mtid of
         Just tid -> withStorage $ loadPackageById (RPLIRepo repo pm) tid
         Nothing -> do
@@ -123,7 +123,7 @@
   where
     withCache inner = do
       pkgs <- forM repoSubdirs $ \(subdir, rpm) -> withStorage $ do
-        loadRepoCache (Repo sRepoUrl sRepoCommit sRepoType subdir) subdir >>= \case
+        loadRepoCache (Repo sRepoUrl sRepoCommit sRepoType subdir) >>= \case
           Just tid -> fmap Right $ (, subdir) <$> loadPackageById (RPLIRepo (Repo sRepoUrl sRepoCommit sRepoType subdir) rpm) tid
           Nothing  -> pure $ Left (subdir, rpm)
       let (missingPkgs, cachedPkgs) = partitionEithers pkgs
diff --git a/src/Pantry/Storage.hs b/src/Pantry/Storage.hs
--- a/src/Pantry/Storage.hs
+++ b/src/Pantry/Storage.hs
@@ -991,13 +991,12 @@
 
 loadRepoCache
   :: Repo
-  -> Text -- ^ subdir
   -> ReaderT SqlBackend (RIO env) (Maybe TreeId)
-loadRepoCache repo subdir = fmap (repoCacheTree . entityVal) <$> selectFirst
+loadRepoCache repo = fmap (repoCacheTree . entityVal) <$> selectFirst
   [ RepoCacheUrl ==. repoUrl repo
   , RepoCacheType ==. repoType repo
   , RepoCacheCommit ==. repoCommit repo
-  , RepoCacheSubdir ==. subdir
+  , RepoCacheSubdir ==. repoSubdir repo
   ]
   [Desc RepoCacheTime]
 
diff --git a/src/Pantry/Types.hs b/src/Pantry/Types.hs
--- a/src/Pantry/Types.hs
+++ b/src/Pantry/Types.hs
@@ -129,7 +129,6 @@
 import RIO.List (intersperse, groupBy)
 import RIO.Time (toGregorian, Day, UTCTime)
 import qualified RIO.Map as Map
-import qualified RIO.HashMap as HM
 import qualified Data.Map.Strict as Map (mapKeysMonotonic)
 import qualified RIO.Set as Set
 import Data.Aeson.Types (toJSONKeyText, Parser)
@@ -164,6 +163,17 @@
 import Database.Persist.SqlBackend.Internal (connRDBMS)
 #endif
 
+#if MIN_VERSION_aeson(2, 0, 0)
+import qualified Data.Aeson.KeyMap as HM
+import qualified Data.Aeson.Key
+
+type AesonKey = Data.Aeson.Key.Key
+#else
+import qualified RIO.HashMap as HM
+
+type AesonKey = Text
+#endif
+
 -- | Parsed tree with more information on the Haskell package it contains.
 --
 -- @since 0.1.0.0
@@ -646,7 +656,7 @@
 instance Display BlobKey where
   display (BlobKey sha size') = display sha <> "," <> display size'
 
-blobKeyPairs :: BlobKey -> [(Text, Value)]
+blobKeyPairs :: BlobKey -> [(AesonKey, Value)]
 blobKeyPairs (BlobKey sha size') =
     [ "sha256" .= sha
     , "size" .= size'
@@ -679,7 +689,7 @@
 instance ToJSONKey PackageNameP where
   toJSONKey =
     ToJSONKeyText
-      (T.pack . packageNameString . unPackageNameP)
+      (fromString . packageNameString . unPackageNameP)
       (unsafeToEncoding . getUtf8Builder . display)
 instance FromJSONKey PackageNameP where
   fromJSONKey = FromJSONKeyText $ PackageNameP . mkPackageName . T.unpack
@@ -1600,7 +1610,7 @@
           RepoGit -> "git"
           RepoHg  -> "hg"
 
-rpmToPairs :: RawPackageMetadata -> [(Text, Value)]
+rpmToPairs :: RawPackageMetadata -> [(AesonKey, Value)]
 rpmToPairs (RawPackageMetadata mname mversion mtree) = concat
   [ maybe [] (\name -> ["name" .= CabalString name]) mname
   , maybe [] (\version -> ["version" .= CabalString version]) mversion
