diff --git a/CHANGES.markdown b/CHANGES.markdown
--- a/CHANGES.markdown
+++ b/CHANGES.markdown
@@ -1,3 +1,11 @@
+## Changes in 0.14.0 [2024.04.30]
+ - Sync with `base-4.20`/GHC 9.10
+ - Backport `foldl'` to `Prelude.Compat`
+ - Backport `List` to `Data.List.Compat` (when building with GHC 9.6 or later)
+ - Backport `append`, `appendList`, `prependList`, `permutations`,
+   `permutations1`, and `sortOn` to `Data.List.NonEmpty.Compat` (when building
+   with GHC 8.0 or later)
+
 ## Changes in 0.13.1 [2023.10.11]
  - Sync with `base-4.19`/GHC 9.8
  - Backport `unzip` to `Data.Functor.Compat`
diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -152,11 +152,13 @@
  * `unsafeFixIO` and `unsafeDupablePerformIO` to `System.IO.Unsafe.IO`
  * `RuntimeRep`-polymorphic `($!)` to `Prelude.Compat`
  * `liftA2` is re-exported from `Prelude.Compat`
+ * `foldl'` is re-exported from `Prelude.Compat`
  * `RuntimeRep`-polymorphic `throw` to `Control.Exception.Compat`
  * `isResourceVanishedError`, `resourceVanishedErrorType`, and
    `isResourceVanishedErrorType` to `System.IO.Error.Compat`
  * `singleton` to `Data.List.Compat` and `Data.List.NonEmpty.Compat`
  * `inits1` and `tails1` to `Data.List.NonEmpty.Compat`
+ * `permutations`, `permutations1`, and `sortOn` to `Data.List.NonEmpty.Compat`
  * `hGetContents'`, `getContents'`, and `readFile'` to `System.IO.Compat`
  * `readBinP` to `Text.Read.Lex.Compat`
  * `withTypeable` and `pattern TypeRep` to `Type.Reflection.Compat`
@@ -165,6 +167,7 @@
  * `heqT` to `Data.Typeable.Compat`
  * `unzip` to `Data.Functor.Compat`
  * `(!?)` and `unsnoc` to `Data.List.Compat`
+ * `List` to `Data.List.Compat` (when building with GHC 9.6 or later)
  * `getSolo` to `Data.Tuple.Compat`
  * `decT` and `hdecT` to `Data.Typeable.Compat`
  * `decTypeRep` to `Type.Reflection.Compat`
@@ -345,6 +348,7 @@
 
 ## Supported versions of GHC/`base`
 
+ * `ghc-9.10.*`  / `base-4.20.*`
  * `ghc-9.8.*`  / `base-4.19.*`
  * `ghc-9.6.*`  / `base-4.18.*`
  * `ghc-9.4.*`  / `base-4.17.*`
diff --git a/base-compat.cabal b/base-compat.cabal
--- a/base-compat.cabal
+++ b/base-compat.cabal
@@ -1,5 +1,5 @@
 name:             base-compat
-version:          0.13.1
+version:          0.14.0
 license:          MIT
 license-file:     LICENSE
 copyright:        (c) 2012-2018 Simon Hengel,
@@ -57,10 +57,11 @@
                   , GHC == 8.8.4
                   , GHC == 8.10.7
                   , GHC == 9.0.2
-                  , GHC == 9.2.7
-                  , GHC == 9.4.5
-                  , GHC == 9.6.2
-                  , GHC == 9.8.1
+                  , GHC == 9.2.8
+                  , GHC == 9.4.8
+                  , GHC == 9.6.5
+                  , GHC == 9.8.2
+                  , GHC == 9.10.1
 
 source-repository head
   type: git
diff --git a/src/Data/List/Compat.hs b/src/Data/List/Compat.hs
--- a/src/Data/List/Compat.hs
+++ b/src/Data/List/Compat.hs
@@ -5,6 +5,11 @@
 #endif
 module Data.List.Compat (
   module Base
+
+#if MIN_VERSION_base(4,18,0) && !(MIN_VERSION_base(4,20,0))
+, List
+#endif
+
 #if !(MIN_VERSION_base(4,19,0))
 , (!?)
 , unsnoc
@@ -103,6 +108,10 @@
 
 #if !(MIN_VERSION_base(4,19,0))
 import Prelude.Compat hiding (foldr, null)
+#endif
+
+#if MIN_VERSION_base(4,18,0) && !(MIN_VERSION_base(4,20,0))
+import GHC.List (List)
 #endif
 
 #if !(MIN_VERSION_base(4,5,0))
diff --git a/src/Data/List/NonEmpty/Compat.hs b/src/Data/List/NonEmpty/Compat.hs
--- a/src/Data/List/NonEmpty/Compat.hs
+++ b/src/Data/List/NonEmpty/Compat.hs
@@ -27,11 +27,15 @@
   , uncons
   , unfoldr
   , sort
+  , sortOn
   , reverse
   , inits
   , inits1
   , tails
   , tails1
+  , append
+  , appendList
+  , prependList
   -- * Building streams
   , iterate
   , repeat
@@ -57,6 +61,8 @@
   , groupBy1
   , groupWith1
   , groupAllWith1
+  , permutations
+  , permutations1
   -- * Sublist predicates
   , isPrefixOf
   -- * \"Set\" operations
@@ -79,7 +85,7 @@
 #if MIN_VERSION_base(4,9,0)
 import Data.List.NonEmpty
 
-# if !(MIN_VERSION_base(4,18,0))
+# if !(MIN_VERSION_base(4,20,0))
 import qualified Prelude.Compat as Prelude
 import Prelude.Compat ((.))
 
@@ -97,6 +103,43 @@
 singleton a = a :| []
 # endif
 
+# if !(MIN_VERSION_base(4,16,0))
+-- | A monomorphic version of 'Prelude.<>' for 'NonEmpty'.
+--
+-- >>> append (1 :| []) (2 :| [3])
+-- 1 :| [2,3]
+--
+-- /Since: 4.16/
+append :: NonEmpty a -> NonEmpty a -> NonEmpty a
+append = (Prelude.<>)
+
+-- | Attach a list at the end of a 'NonEmpty'.
+--
+-- >>> appendList (1 :| [2,3]) []
+-- 1 :| [2,3]
+--
+-- >>> appendList (1 :| [2,3]) [4,5]
+-- 1 :| [2,3,4,5]
+--
+-- /Since: 4.16/
+appendList :: NonEmpty a -> [a] -> NonEmpty a
+appendList (x :| xs) ys = x :| xs Prelude.<> ys
+
+-- | Attach a list at the beginning of a 'NonEmpty'.
+--
+-- >>> prependList [] (1 :| [2,3])
+-- 1 :| [2,3]
+--
+-- >>> prependList [negate 1, 0] (1 :| [2, 3])
+-- -1 :| [0,1,2,3]
+--
+-- /Since: 4.16/
+prependList :: [a] -> NonEmpty a -> NonEmpty a
+prependList ls ne = case ls of
+  [] -> ne
+  (x : xs) -> x :| xs Prelude.<> toList ne
+# endif
+
 # if !(MIN_VERSION_base(4,18,0))
 -- | The 'inits1' function takes a 'NonEmpty' stream @xs@ and returns all the
 -- 'NonEmpty' finite prefixes of @xs@, starting with the shortest.
@@ -133,5 +176,71 @@
   -- - Therefore, if we take all but the last element of `tails xs` i.e.
   --   `init (tails xs)`, we have a nonempty list of nonempty lists
   fromList . Prelude.map fromList . List.init . List.tails . Foldable.toList
+# endif
+
+# if !(MIN_VERSION_base(4,20,0))
+-- | The 'permutations' function returns the list of all permutations of the argument.
+--
+-- /Since: 4.20.0.0/
+permutations            :: [a] -> NonEmpty [a]
+permutations xs0        =  xs0 :| perms xs0 []
+  where
+    perms []     _  = []
+    perms (t:ts) is = List.foldr interleave (perms ts (t:is)) (permutations is)
+      where interleave    xs     r = let (_,zs) = interleave' Prelude.id xs r in zs
+            interleave' _ []     r = (ts, r)
+            interleave' f (y:ys) r = let (us,zs) = interleave' (f . (y:)) ys r
+                                     in  (y:us, f (t:y:us) : zs)
+-- The implementation of 'permutations' is adopted from 'GHC.Internal.Data.List.permutations',
+-- see there for discussion and explanations.
+
+-- | 'permutations1' operates like 'permutations', but uses the knowledge that its input is
+-- non-empty to produce output where every element is non-empty.
+--
+-- > permutations1 = fmap fromList . permutations . toList
+--
+-- /Since: 4.20.0.0/
+permutations1 :: NonEmpty a -> NonEmpty (NonEmpty a)
+permutations1 xs = fromList Prelude.<$> permutations (toList xs)
+
+-- | Sort a 'NonEmpty' on a user-supplied projection of its elements.
+-- See 'List.sortOn' for more detailed information.
+--
+-- ==== __Examples__
+--
+-- >>> sortOn fst $ (2, "world") :| [(4, "!"), (1, "Hello")]
+-- (1,"Hello") :| [(2,"world"),(4,"!")]
+--
+-- >>> sortOn length $ "jim" :| ["creed", "pam", "michael", "dwight", "kevin"]
+-- "jim" :| ["pam","creed","kevin","dwight","michael"]
+--
+-- ==== __Performance notes__
+--
+-- This function minimises the projections performed, by materialising
+-- the projections in an intermediate list.
+--
+-- For trivial projections, you should prefer using 'sortBy' with
+-- 'comparing', for example:
+--
+-- >>> sortBy (comparing fst) $ (3, 1) :| [(2, 2), (1, 3)]
+-- (1,3) :| [(2,2),(3,1)]
+--
+-- Or, for the exact same API as 'sortOn', you can use `sortBy . comparing`:
+--
+-- >>> (sortBy . comparing) fst $ (3, 1) :| [(2, 2), (1, 3)]
+-- (1,3) :| [(2,2),(3,1)]
+--
+-- 'sortWith' is an alias for `sortBy . comparing`.
+--
+-- /Since: 4.20.0.0/
+sortOn :: Prelude.Ord b => (a -> b) -> NonEmpty a -> NonEmpty a
+sortOn f = lift (List.sortOn f)
+
+-- | Lift list operations to work on a 'NonEmpty' stream.
+--
+-- /Beware/: If the provided function returns an empty list,
+-- this will raise an error.
+lift :: Foldable.Foldable f => ([a] -> [b]) -> f a -> NonEmpty b
+lift f = fromList . f . Foldable.toList
 # endif
 #endif
diff --git a/src/Prelude/Compat.hs b/src/Prelude/Compat.hs
--- a/src/Prelude/Compat.hs
+++ b/src/Prelude/Compat.hs
@@ -7,11 +7,11 @@
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE TypeInType #-}
 #endif
-#if MIN_VERSION_base(4,17,0) && !(MIN_VERSION_base(4,18,0))
+#if MIN_VERSION_base(4,17,0) && !(MIN_VERSION_base(4,20,0))
 {-# LANGUAGE ExplicitNamespaces #-}
 #endif
 module Prelude.Compat (
-#if MIN_VERSION_base(4,18,0)
+#if MIN_VERSION_base(4,20,0)
   module Base
 #else
   either
@@ -119,6 +119,7 @@
 , elem
 , foldMap
 , foldl
+, foldl'
 , foldl1
 , foldr
 , foldr1
@@ -297,6 +298,10 @@
 
 # if !(MIN_VERSION_base(4,18,0))
 import Control.Applicative (liftA2)
+# endif
+
+# if !(MIN_VERSION_base(4,20,0))
+import Data.Foldable (foldl')
 # endif
 
 #else
