diff --git a/antiope-s3.cabal b/antiope-s3.cabal
--- a/antiope-s3.cabal
+++ b/antiope-s3.cabal
@@ -2,10 +2,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: dcb3f417b4062c75af23d1ec15dc56f6716f85eee96904d1fc2edabc82bb4571
+-- hash: dcc45e2141245948130744f91b90759cacc398086b9b431ceff34ad08b9a9b82
 
 name:           antiope-s3
-version:        4.0.1
+version:        5.0.0
 description:    Please see the README on Github at <https://github.com/arbor/antiope#readme>
 category:       Services
 homepage:       https://github.com/arbor/antiope#readme
@@ -49,7 +49,6 @@
     , unliftio-core
   exposed-modules:
       Antiope.S3
-      Antiope.S3.Classy
       Antiope.S3.Internal
       Antiope.S3.Types
   other-modules:
diff --git a/src/Antiope/S3.hs b/src/Antiope/S3.hs
--- a/src/Antiope/S3.hs
+++ b/src/Antiope/S3.hs
@@ -21,7 +21,7 @@
 import Antiope.S3.Types             (S3Uri (S3Uri))
 import Control.Lens
 import Control.Monad
-import Control.Monad.Catch          (MonadCatch, catch)
+import Control.Monad.Catch          (catch)
 import Control.Monad.Trans.AWS      hiding (send)
 import Control.Monad.Trans.Resource
 import Data.ByteString.Lazy         (ByteString, empty)
@@ -31,7 +31,7 @@
 import Data.Conduit.List            (unfoldM)
 import Data.Monoid                  ((<>))
 import Data.Text                    (Text, pack, unpack)
-import Network.AWS                  (Error (..), ServiceError (..))
+import Network.AWS                  (Error (..), MonadAWS, ServiceError (..))
 import Network.AWS.Data
 import Network.AWS.Data.Body        (_streamBody)
 import Network.AWS.S3
@@ -52,80 +52,70 @@
   let k = pack $ drop 1 $ puri & uriPath
   pure $ S3Uri (BucketName b) (ObjectKey k)
 
-downloadLBS :: (MonadResource m, HasEnv e)
-  => e
-  -> BucketName
+downloadLBS :: MonadAWS m
+  => BucketName
   -> ObjectKey
   -> m ByteString
-downloadLBS e bucketName objectKey = AWS.runAWS e $ do
+downloadLBS bucketName objectKey = do
   resp <- AWS.send $ getObject bucketName objectKey
   (resp ^. gorsBody) `sinkBody` sinkLbs
 
-downloadLBS' :: (MonadResource m, MonadCatch m, HasEnv e)
-  => e
-  -> BucketName
+downloadLBS' :: MonadAWS m
+  => BucketName
   -> ObjectKey
   -> m (Maybe ByteString)
-downloadLBS' e bucketName objectKey = do
-  ebs <- (Right <$> downloadLBS e bucketName objectKey) `catch` \(err :: Error) -> case err of
+downloadLBS' bucketName objectKey = do
+  ebs <- (Right <$> downloadLBS bucketName objectKey) `catch` \(err :: Error) -> case err of
     (ServiceError (ServiceError' _ (Status 404 _) _ _ _ _)) -> return (Left empty)
     _                                                       -> throwM err
   case ebs of
     Right bs -> return (Just bs)
     Left _   -> return Nothing
 
-downloadS3Uri :: (MonadResource m, MonadCatch m, HasEnv e)
-  => e
-  -> S3Uri
+downloadS3Uri :: MonadAWS m
+  => S3Uri
   -> m (Maybe ByteString)
-downloadS3Uri e (S3Uri b k) = downloadLBS' e b k
+downloadS3Uri (S3Uri b k) = downloadLBS' b k
 
-s3ObjectSource :: (MonadResource m, HasEnv e)
-  => e
-  -> BucketName
+s3ObjectSource :: (MonadAWS m, MonadResource m)
+  => BucketName
   -> ObjectKey
   -> m (ConduitT () BS.ByteString m ())
-s3ObjectSource e bkt obj = do
-  resp <- AWS.runAWS e $ AWS.send $ getObject bkt obj
+s3ObjectSource bkt obj = do
+  resp <- AWS.send $ getObject bkt obj
   return $ transPipe liftResourceT $ _streamBody $ resp ^. gorsBody
 
 -- | Puts file into a specified S3 bucket
-putFile :: (HasEnv e, MonadUnliftIO m)
-  => e
-  -> BucketName       -- ^ Target bucket
+putFile :: MonadAWS m
+  => BucketName       -- ^ Target bucket
   -> ObjectKey        -- ^ File name on S3
   -> FilePath         -- ^ Source file path
   -> m (Maybe ETag)   -- ^ Etag when the operation is successful
-putFile e b k f = AWS.runResourceT . AWS.runAWS e $ do
+putFile b k f = do
     req <- chunkedFile chunkSize f
     view porsETag <$> AWS.send (putObject b k req)
 
-putContent :: (MonadUnliftIO m, HasEnv e)
-  => e
-  -> BucketName
+putContent :: MonadAWS m
+  => BucketName
   -> ObjectKey
   -> ByteString
   -> m (Maybe ETag)
-putContent e b k c = AWS.runResourceT . AWS.runAWS e $
-  view porsETag <$> AWS.send (putObject b k (toBody c))
+putContent b k c = view porsETag <$> AWS.send (putObject b k (toBody c))
 
-putContent' :: (MonadUnliftIO m, HasEnv e)
-  => e
-  -> S3Uri
+putContent' :: MonadAWS m
+  => S3Uri
   -> ByteString
   -> m (Maybe ETag)
-putContent' e (S3Uri b k) = putContent e b k
+putContent' (S3Uri b k) = putContent b k
 
 -- | Copies a single object within S3
-copySingle :: (MonadUnliftIO m, HasEnv e)
-  => e
-  -> BucketName          -- ^ Source bucket name
+copySingle :: MonadAWS m
+  => BucketName          -- ^ Source bucket name
   -> ObjectKey           -- ^ Source key
   -> BucketName          -- ^ Target bucket name
   -> ObjectKey           -- ^ Target key
   -> m ()
-copySingle e sb sk tb tk = AWS.runResourceT . AWS.runAWS e $
-  void . AWS.send $ copyObject tb (toText sb <> "/" <> toText sk) tk
+copySingle sb sk tb tk = void . AWS.send $ copyObject tb (toText sb <> "/" <> toText sk) tk
      & coMetadataDirective ?~ MDCopy
 
 -- Private --
@@ -137,12 +127,11 @@
   initial & lovContinuationToken .~ resp ^. lovrsNextContinuationToken
 
 -- The type signature is like this so that it can be used with `unfoldM`
-lsBucketPage :: (MonadUnliftIO m, HasEnv e)
-  => e
-  -> Maybe ListObjectsV2
+lsBucketPage :: MonadAWS m
+  => Maybe ListObjectsV2
   -> m (Maybe (ListObjectsV2Response, Maybe ListObjectsV2))
-lsBucketPage _ Nothing    = pure Nothing
-lsBucketPage e (Just req) = AWS.runResourceT . AWS.runAWS e $ do
+lsBucketPage Nothing    = pure Nothing
+lsBucketPage (Just req) = do
   resp <- AWS.send req
   pure . Just . (resp, ) $
     case resp ^. lovrsIsTruncated of
@@ -152,8 +141,7 @@
 -- | Streams the entire set of results (i.e. all pages) of a ListObjectsV2
 -- request from S3.
 -- lsBucketStream :: MonadAWS m => ListObjectsV2 -> ConduitT i Object m ()
-lsBucketStream :: (HasEnv e, MonadUnliftIO m)
-  => e
-  -> ListObjectsV2
+lsBucketStream :: MonadAWS m
+  => ListObjectsV2
   -> ConduitM a Object m ()
-lsBucketStream e bar = unfoldM (lsBucketPage e) (Just bar) .| CC.concatMap (^. lovrsContents)
+lsBucketStream bar = unfoldM lsBucketPage (Just bar) .| CC.concatMap (^. lovrsContents)
diff --git a/src/Antiope/S3/Classy.hs b/src/Antiope/S3/Classy.hs
deleted file mode 100644
--- a/src/Antiope/S3/Classy.hs
+++ /dev/null
@@ -1,147 +0,0 @@
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TupleSections       #-}
-
-module Antiope.S3.Classy
-( downloadLBS
-, downloadLBS'
-, downloadS3Uri
-, s3ObjectSource
-, putFile, putContent , putContent'
-, copySingle
-, fromS3Uri
-, toS3Uri
-, lsBucketStream
-, BucketName(..)
-, ObjectKey(..)
-, ETag(..)
-, S3Uri(..)
-) where
-
-import Antiope.S3.Internal
-import Antiope.S3.Types             (S3Uri (S3Uri))
-import Control.Lens
-import Control.Monad
-import Control.Monad.Catch          (catch)
-import Control.Monad.Trans.AWS      hiding (send)
-import Control.Monad.Trans.Resource
-import Data.ByteString.Lazy         (ByteString, empty)
-import Data.Conduit
-import Data.Conduit.Binary          (sinkLbs)
-import Data.Conduit.Combinators     as CC (concatMap)
-import Data.Conduit.List            (unfoldM)
-import Data.Monoid                  ((<>))
-import Data.Text                    (Text, pack, unpack)
-import Network.AWS                  (Error (..), MonadAWS, ServiceError (..))
-import Network.AWS.Data
-import Network.AWS.Data.Body        (_streamBody)
-import Network.AWS.S3
-import Network.HTTP.Types.Status    (Status (..))
-import Network.URI                  (URI (..), URIAuth (..), parseURI)
-
-import qualified Data.ByteString as BS
-import qualified Network.AWS     as AWS
-
-chunkSize :: ChunkSize
-chunkSize = ChunkSize (1024 * 1024)
-
-fromS3Uri :: Text -> Maybe S3Uri
-fromS3Uri uri = do
-  puri <- parseURI (unpack uri)
-  auth <- puri & uriAuthority
-  let b = pack $ auth & uriRegName       -- URI lib is pretty weird
-  let k = pack $ drop 1 $ puri & uriPath
-  pure $ S3Uri (BucketName b) (ObjectKey k)
-
-downloadLBS :: MonadAWS m
-  => BucketName
-  -> ObjectKey
-  -> m ByteString
-downloadLBS bucketName objectKey = do
-  resp <- AWS.send $ getObject bucketName objectKey
-  (resp ^. gorsBody) `sinkBody` sinkLbs
-
-downloadLBS' :: MonadAWS m
-  => BucketName
-  -> ObjectKey
-  -> m (Maybe ByteString)
-downloadLBS' bucketName objectKey = do
-  ebs <- (Right <$> downloadLBS bucketName objectKey) `catch` \(err :: Error) -> case err of
-    (ServiceError (ServiceError' _ (Status 404 _) _ _ _ _)) -> return (Left empty)
-    _                                                       -> throwM err
-  case ebs of
-    Right bs -> return (Just bs)
-    Left _   -> return Nothing
-
-downloadS3Uri :: MonadAWS m
-  => S3Uri
-  -> m (Maybe ByteString)
-downloadS3Uri (S3Uri b k) = downloadLBS' b k
-
-s3ObjectSource :: (MonadAWS m, MonadResource m)
-  => BucketName
-  -> ObjectKey
-  -> m (ConduitT () BS.ByteString m ())
-s3ObjectSource bkt obj = do
-  resp <- AWS.send $ getObject bkt obj
-  return $ transPipe liftResourceT $ _streamBody $ resp ^. gorsBody
-
--- | Puts file into a specified S3 bucket
-putFile :: MonadAWS m
-  => BucketName       -- ^ Target bucket
-  -> ObjectKey        -- ^ File name on S3
-  -> FilePath         -- ^ Source file path
-  -> m (Maybe ETag)   -- ^ Etag when the operation is successful
-putFile b k f = do
-    req <- chunkedFile chunkSize f
-    view porsETag <$> AWS.send (putObject b k req)
-
-putContent :: MonadAWS m
-  => BucketName
-  -> ObjectKey
-  -> ByteString
-  -> m (Maybe ETag)
-putContent b k c = view porsETag <$> AWS.send (putObject b k (toBody c))
-
-putContent' :: MonadAWS m
-  => S3Uri
-  -> ByteString
-  -> m (Maybe ETag)
-putContent' (S3Uri b k) = putContent b k
-
--- | Copies a single object within S3
-copySingle :: MonadAWS m
-  => BucketName          -- ^ Source bucket name
-  -> ObjectKey           -- ^ Source key
-  -> BucketName          -- ^ Target bucket name
-  -> ObjectKey           -- ^ Target key
-  -> m ()
-copySingle sb sk tb tk = void . AWS.send $ copyObject tb (toText sb <> "/" <> toText sk) tk
-     & coMetadataDirective ?~ MDCopy
-
--- Private --
-
--- Builds the request for the next page of a NextObjectsV2 request,
--- based on the original request and the most recent response.
-nextPageReq :: ListObjectsV2 -> ListObjectsV2Response -> ListObjectsV2
-nextPageReq initial resp =
-  initial & lovContinuationToken .~ resp ^. lovrsNextContinuationToken
-
--- The type signature is like this so that it can be used with `unfoldM`
-lsBucketPage :: MonadAWS m
-  => Maybe ListObjectsV2
-  -> m (Maybe (ListObjectsV2Response, Maybe ListObjectsV2))
-lsBucketPage Nothing    = pure Nothing
-lsBucketPage (Just req) = do
-  resp <- AWS.send req
-  pure . Just . (resp, ) $
-    case resp ^. lovrsIsTruncated of
-      Just True -> Just $ nextPageReq req resp
-      _         -> Nothing
-
--- | Streams the entire set of results (i.e. all pages) of a ListObjectsV2
--- request from S3.
--- lsBucketStream :: MonadAWS m => ListObjectsV2 -> ConduitT i Object m ()
-lsBucketStream :: MonadAWS m
-  => ListObjectsV2
-  -> ConduitM a Object m ()
-lsBucketStream bar = unfoldM lsBucketPage (Just bar) .| CC.concatMap (^. lovrsContents)
