diff --git a/AddHandler.hs b/AddHandler.hs
--- a/AddHandler.hs
+++ b/AddHandler.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE PatternGuards #-}
+
 module AddHandler (addHandler) where
 
 import Prelude hiding (readFile)
@@ -245,7 +246,9 @@
 
 getSrcDir :: FilePath -> IO FilePath
 getSrcDir cabal = do
-#if MIN_VERSION_Cabal(2, 0, 0)
+#if MIN_VERSION_Cabal(3, 14, 0)
+    pd <- flattenPackageDescription <$> readGenericPackageDescription normal Nothing (relativeSymbolicPath $ makeRelativePathEx cabal)
+#elif MIN_VERSION_Cabal(2, 0, 0)
     pd <- flattenPackageDescription <$> readGenericPackageDescription normal cabal
 #else
     pd <- flattenPackageDescription <$> readPackageDescription normal cabal
diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # ChangeLog for yesod-bin
 
+## 1.6.2.4
+
+* Set `base >= 4.11` for less CPP and imports [#1876](https://github.com/yesodweb/yesod/pull/1876)
+
 ## 1.6.2.3
 
 * Support optparse-applicative-0.18 [#1829](https://github.com/yesodweb/yesod/pull/1829)
diff --git a/Devel.hs b/Devel.hs
--- a/Devel.hs
+++ b/Devel.hs
@@ -1,7 +1,8 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE CPP                 #-}
-{-# LANGUAGE OverloadedStrings   #-}
-{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TemplateHaskell #-}
+
 module Devel
     ( devel
     , develSignal
@@ -29,14 +30,16 @@
 import qualified Distribution.Package                  as D
 import qualified Distribution.PackageDescription       as D
 #if MIN_VERSION_Cabal(3,8,0)
-import qualified Distribution.Simple.PackageDescription as D
-#endif
-#if MIN_VERSION_Cabal(2, 2, 0)
-import qualified Distribution.PackageDescription.Parsec as D
+import qualified Distribution.Simple.PackageDescription as D (readGenericPackageDescription)
+#elif MIN_VERSION_Cabal(2, 2, 0)
+import qualified Distribution.PackageDescription.Parsec as D (readGenericPackageDescription)
 #else
-import qualified Distribution.PackageDescription.Parse as D
+import qualified Distribution.PackageDescription.Parse as D (readGenericPackageDescription)
 #endif
-import qualified Distribution.Simple.Utils             as D
+import qualified Distribution.Simple.Utils             as D (tryFindPackageDesc)
+#if MIN_VERSION_Cabal(3,14,0)
+import qualified Distribution.Utils.Path               as D (relativeSymbolicPath)
+#endif
 import qualified Distribution.Verbosity                as D
 import           Network.HTTP.Client                   (newManager)
 import           Network.HTTP.Client                   (managerSetProxy,
@@ -292,7 +295,9 @@
 
     -- Find out the name of our package, needed for the upcoming Stack
     -- commands
-#if MIN_VERSION_Cabal(3, 0, 0)
+#if MIN_VERSION_Cabal(3, 14, 0)
+    cabal  <- D.tryFindPackageDesc D.silent Nothing
+#elif MIN_VERSION_Cabal(3, 0, 0)
     cabal  <- D.tryFindPackageDesc D.silent "."
 #elif MIN_VERSION_Cabal(1, 20, 0)
     cabal  <- D.tryFindPackageDesc "."
@@ -300,7 +305,9 @@
     cabal  <- D.findPackageDesc "."
 #endif
 
-#if MIN_VERSION_Cabal(2, 0, 0)
+#if MIN_VERSION_Cabal(3, 14, 0)
+    gpd    <- D.readGenericPackageDescription D.normal Nothing (D.relativeSymbolicPath cabal)
+#elif MIN_VERSION_Cabal(2, 0, 0)
     gpd    <- D.readGenericPackageDescription D.normal cabal
 #else
     gpd    <- D.readPackageDescription D.normal cabal
@@ -308,7 +315,7 @@
 
     let pd = D.packageDescription gpd
         D.PackageIdentifier packageNameWrapped _version = D.package pd
-#if MIN_VERSION_Cabal(2, 0, 0)
+#if MIN_VERSION_Cabal(1, 22, 0)
         packageName = D.unPackageName packageNameWrapped
 #else
         D.PackageName packageName = packageNameWrapped
@@ -386,7 +393,11 @@
         -- changing the destination port for reverse proxying to -1. We also
         -- make sure that all content to stdout or stderr from the build
         -- process is piped to the actual stdout and stderr handles.
+#if MIN_VERSION_conduit_extra(1,3,4)
+        withProcessTerm_ procConfig $ \p -> do
+#else
         withProcess_ procConfig $ \p -> do
+#endif
             let helper getter h =
                       runConduit
                     $ getter p
@@ -503,7 +514,11 @@
             sayV $ "Running child process: " ++ show procDef
 
             -- Start running the child process with GHC
+#if MIN_VERSION_conduit_extra(1,3,4)
+            withProcessTerm procDef $ \p -> do
+#else
             withProcess procDef $ \p -> do
+#endif
                 -- Wait for either the process to exit, or for a new build to come through
                 eres <- atomically (fmap Left (waitExitCodeSTM p) <|> fmap Right
                     (do changed <- readTVar changedVar
diff --git a/HsFile.hs b/HsFile.hs
--- a/HsFile.hs
+++ b/HsFile.hs
@@ -1,10 +1,8 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE OverloadedStrings #-}
 module HsFile (mkHsFile) where
+
 import Text.ProjectTemplate (createTemplate)
 import Conduit
 import qualified Data.ByteString as BS
-import Control.Monad.IO.Class (liftIO)
 import Data.String (fromString)
 
 mkHsFile :: IO ()
diff --git a/Keter.hs b/Keter.hs
--- a/Keter.hs
+++ b/Keter.hs
@@ -1,5 +1,6 @@
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+
 module Keter
     ( keter
     ) where
@@ -18,7 +19,6 @@
 import Control.Monad
 import System.Directory hiding (findFiles)
 import Data.Maybe (mapMaybe,isJust,maybeToList)
-import Data.Monoid
 import System.FilePath ((</>))
 import qualified Codec.Archive.Tar as Tar
 import Control.Exception
@@ -39,7 +39,11 @@
       -> IO ()
 keter cabal noBuild noCopyTo buildArgs = do
     ketercfg <- keterConfig
+#if MIN_VERSION_yaml(0,8,4)
+    mvalue <- decodeFileEither ketercfg >>= either throwIO pure
+#else
     mvalue <- decodeFile ketercfg
+#endif
     value <-
         case mvalue of
             Nothing -> error "No config/keter.yaml found"
@@ -93,7 +97,7 @@
             useStack = inStackExec || isJust mStackYaml || stackQueryRunSuccess
 
         if useStack
-            then do let stackYaml = maybeToList $ fmap ("--stack-yaml="<>) mStackYaml
+            then do let stackYaml = maybeToList $ fmap ("--stack-yaml=" <>) mStackYaml
                         localBinPath = cwd' </> "dist/bin"
                     run "stack" $ stackYaml <> ["clean"]
                     createDirectoryIfMissing True localBinPath
diff --git a/Options.hs b/Options.hs
--- a/Options.hs
+++ b/Options.hs
@@ -1,20 +1,18 @@
-{-# LANGUAGE PatternGuards       #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE PatternGuards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE CPP                 #-}
 
 module Options (injectDefaults) where
 
-import           Control.Applicative
 import qualified Control.Exception         as E
-import           Control.Monad
-import           Control.Monad.Trans.Except
-import           Control.Monad.Trans.Reader
+import           Control.Monad             (msum)
+import           Control.Monad.Trans.Except (runExcept, throwE)
+import           Control.Monad.Trans.Reader (runReaderT)
 import           Data.Char                 (isAlphaNum, isSpace, toLower)
 import           Data.List                 (foldl')
 import           Data.List.Split           (splitOn)
 import qualified Data.Map                  as M
 import           Data.Maybe                (mapMaybe)
-import           Data.Monoid
 import           Options.Applicative
 import           Options.Applicative.Types
 import           System.Directory
@@ -40,7 +38,7 @@
   e      <- getEnvironment
   config <- (readFile . (</> "config") =<< getAppUserDataDirectory prefix)
               `E.catch` \(_::E.SomeException) -> return ""
-  let env = M.fromList . filter ((==[prefix]) . take 1 . fst) $
+  let env = M.fromList . filter ((== [prefix]) . take 1 . fst) $
                configLines config <>                              -- config first
                map (\(k,v) -> (splitOn "_" $ map toLower k, v)) e -- env vars override config
       p' =  parser { infoParser = injectDefaultP env [prefix] (infoParser parser) }
@@ -54,10 +52,10 @@
 
 -- | really simple key/value file reader:   x.y = z -> (["x","y"],"z")
 configLines :: String -> [([String], String)]
-configLines = mapMaybe (mkLine . takeWhile (/='#')) . lines
+configLines = mapMaybe (mkLine . takeWhile (/= '#')) . lines
   where
     trim = let f = reverse . dropWhile isSpace in f . f
-    mkLine l | (k, '=':v) <- break (=='=') l = Just (splitOn "." (trim k), trim v)
+    mkLine l | (k, '=':v) <- break (== '=') l = Just (splitOn "." (trim k), trim v)
              | otherwise                       = Nothing
 
 -- | inject the environment into the parser
@@ -86,17 +84,19 @@
                           . getEnvValue env path)
                         names)
   | (Option (FlagReader names a) _) <- o =
-     p <|> if any ((==Just "1") . getEnvValue env path) names then pure a else empty
+     p <|> if any ((== Just "1") . getEnvValue env path) names then pure a else empty
   | otherwise = p
   where
     modifyParserI cmd parseri =
         parseri { infoParser = injectDefaultP env (path ++ [normalizeName cmd]) (infoParser parseri) }
-    cmdMap f cmds = 
+#if !MIN_VERSION_optparse_applicative(0,18,0)
+    cmdMap f cmds =
         let mkCmd cmd =
-                let (Just parseri) = f cmd
-                in  modifyParserI cmd parseri
+                case f cmd of
+                    Nothing -> error "yesod-bin/Options.injectDefaultP: should never happen"
+                    Just parseri -> modifyParserI cmd parseri
         in  M.fromList (map (\c -> (c, mkCmd c)) cmds)
-
+#endif
 
 injectDefaultP env path (MultP p1 p2) =
    MultP (injectDefaultP env path p1) (injectDefaultP env path p2)
@@ -110,4 +110,3 @@
 
 normalizeName :: String -> String
 normalizeName = map toLower . filter isAlphaNum
-
diff --git a/main.hs b/main.hs
--- a/main.hs
+++ b/main.hs
@@ -1,8 +1,7 @@
-{-# LANGUAGE CPP             #-}
-{-# LANGUAGE RecordWildCards             #-}
+{-# LANGUAGE RecordWildCards #-}
+
 module Main (main) where
 
-import           Data.Monoid
 import           Data.Version           (showVersion)
 import           Options.Applicative
 import           System.Exit            (exitFailure)
diff --git a/yesod-bin.cabal b/yesod-bin.cabal
--- a/yesod-bin.cabal
+++ b/yesod-bin.cabal
@@ -1,5 +1,5 @@
 name:            yesod-bin
-version:         1.6.2.3
+version:         1.6.2.4
 license:         MIT
 license-file:    LICENSE
 author:          Michael Snoyman <michael@snoyman.com>
@@ -25,13 +25,12 @@
     if os(openbsd)
         ld-options:      -Wl,-zwxneeded
 
-    build-depends:     base               >= 4.10         && < 5
+    build-depends:     base               >= 4.11         && < 5
                      , Cabal              >= 1.18
                      , bytestring         >= 0.9.1.4
                      , conduit            >= 1.3
                      , conduit-extra      >= 1.3
                      , containers         >= 0.2
-                     , data-default-class
                      , directory          >= 1.2.1
                      , file-embed
                      , filepath           >= 1.1
@@ -48,12 +47,12 @@
                      , split              >= 0.2          && < 0.3
                      , stm
                      , streaming-commons
-                     , tar                >= 0.4          && < 0.6
+                     , tar                >= 0.4          && < 0.7
                      , text               >= 0.11
                      , time               >= 1.1.4
                      , transformers
-                     , transformers-compat
                      , unliftio
+                     -- only necessary if 'aeson < 2.0'
                      , unordered-containers
                      , wai                >= 2.0
                      , wai-extra
