diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+# log-elasticsearch-0.13.0.0 (2022-09-21)
+* Remove deprecated `elasticSearchLogger`.
+* Use `http-client-openssl` by default instead of `http-client-tls`.
+* Generalize logger related functions to `MonadUnliftIO`.
+
 # log-elasticsearch-0.12.2.0 (2022-04-04)
 * Add support for aeson 2.0.1.0.
 * Add support for GHC 9.2.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,3 +1,40 @@
-# log-elasticsearch [![Hackage version](https://img.shields.io/hackage/v/log-elasticsearch.svg?label=Hackage)](https://hackage.haskell.org/package/log-elasticsearch) [![Build Status](https://secure.travis-ci.org/scrive/log.svg?branch=master)](http://travis-ci.org/scrive/log)
+# log
 
-Elasticsearch back end for the `log` library suite.
+[![Hackage version](https://img.shields.io/hackage/v/log-base.svg?label=Hackage)](https://hackage.haskell.org/package/log-base)
+[![Build Status](https://github.com/scrive/log/workflows/Haskell-CI/badge.svg?branch=master)](https://github.com/scrive/log/actions?query=branch%3Amaster)
+
+A set of libraries that provide a way to record structured log messages with
+multiple backends.
+
+Supported backends:
+
+* Standard output via
+  [`log-base`](https://hackage.haskell.org/package/log-base).
+* Elasticsearch via
+  [`log-elasticsearch`](https://hackage.haskell.org/package/log-elasticsearch).
+* PostgreSQL via
+  [`log-postgres`](https://hackage.haskell.org/package/log-postgres).
+
+## Example
+
+A sample usage for logging to both standard output and Elasticsearch:
+
+```haskell
+{-# LANGUAGE OverloadedStrings #-}
+module Main where
+
+import Log
+import Log.Backend.ElasticSearch
+import Log.Backend.StandardOutput
+
+main :: IO ()
+main = do
+  let config = defaultElasticSearchConfig
+        { esServer = "http://localhost:9200"
+        , esIndex  = "logs"
+        }
+  withStdOutLogger $ \stdoutLogger -> do
+    withElasticSearchLogger config $ \esLogger -> do
+      runLogT "main" (stdoutLogger <> esLogger) defaultLogLevel $ do
+        logInfo_ "Hi there"
+```
diff --git a/log-elasticsearch.cabal b/log-elasticsearch.cabal
--- a/log-elasticsearch.cabal
+++ b/log-elasticsearch.cabal
@@ -1,5 +1,5 @@
 name:                log-elasticsearch
-version:             0.12.2.0
+version:             0.13.0.0
 synopsis:            Structured logging solution (Elasticsearch back end)
 
 description:         Elasticsearch back end for the 'log' library suite.
@@ -18,12 +18,16 @@
 build-type:          Simple
 cabal-version:       >=1.10
 extra-source-files:  CHANGELOG.md, README.md
-tested-with:         GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.2
+tested-with:         GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.4 || ==9.4.2
 
 Source-repository head
   Type:     git
   Location: https://github.com/scrive/log.git
 
+flag openssl
+  Description:   Use http-client-openssl instead of http-client-tls
+  Default:       True
+
 library
   exposed-modules:     Log.Backend.ElasticSearch
                        Log.Backend.ElasticSearch.Internal
@@ -35,15 +39,15 @@
                        bytestring,
                        deepseq,
                        http-client,
-                       http-client-tls,
                        http-types,
-                       log-base >= 0.10 && <0.12,
+                       log-base >= 0.10 && <0.13,
                        network-uri,
                        semigroups,
                        text,
                        text-show >= 2,
                        time >= 1.5,
                        transformers,
+                       unliftio-core >= 0.2,
                        unordered-containers,
                        vector
   hs-source-dirs:      src
@@ -57,7 +61,6 @@
                     , GeneralizedNewtypeDeriving
                     , LambdaCase
                     , MultiParamTypeClasses
-                    , NoImplicitPrelude
                     , OverloadedStrings
                     , RankNTypes
                     , RecordWildCards
@@ -65,3 +68,9 @@
                     , TupleSections
                     , TypeFamilies
                     , UndecidableInstances
+
+  if flag(openssl)
+    cpp-options: -DOPENSSL
+    build-depends: http-client-openssl >= 0.3.2
+  else
+    build-depends: http-client-tls
diff --git a/src/Log/Backend/ElasticSearch.hs b/src/Log/Backend/ElasticSearch.hs
--- a/src/Log/Backend/ElasticSearch.hs
+++ b/src/Log/Backend/ElasticSearch.hs
@@ -12,23 +12,21 @@
   , checkElasticSearchConnection
   , defaultElasticSearchConfig
   , withElasticSearchLogger
-  , elasticSearchLogger
   ) where
 
 import Control.Applicative
 import Control.Concurrent
 import Control.Exception
 import Control.Monad
+import Control.Monad.IO.Unlift
 import Data.Aeson
 import Data.Aeson.Encode.Pretty
 import Data.IORef
 import Data.Maybe
-import Data.Semigroup
 import Data.Time
 import Log
 import Log.Internal.Logger
 import Network.HTTP.Client
-import Prelude
 import qualified Data.Text as T
 import qualified Data.Text.IO as T
 import qualified Data.Text.Lazy as TL
@@ -43,12 +41,10 @@
 -- | Create an 'elasticSearchLogger' for the duration of the given
 -- action, and shut it down afterwards, making sure that all buffered
 -- messages are actually written to the Elasticsearch store.
-withElasticSearchLogger :: ElasticSearchConfig -> (Logger -> IO r) -> IO r
-withElasticSearchLogger conf act = do
+withElasticSearchLogger :: MonadUnliftIO m => ElasticSearchConfig -> (Logger -> m r) -> m r
+withElasticSearchLogger conf act = withRunInIO $ \unlift -> do
   logger <- elasticSearchLogger conf
-  withLogger logger act
-
-{-# DEPRECATED elasticSearchLogger "Use 'withElasticSearchLogger' instead!" #-}
+  withLogger logger (unlift . act)
 
 -- | Start an asynchronous logger thread that stores messages using
 -- Elasticsearch.
@@ -198,25 +194,27 @@
                . encodePrettyToTextBuilder' defConfig { confIndent = Spaces 2 }
 
     toJsonMsg :: LogMessage -> Object
-    toJsonMsg msg = let Object jMsg = toJSON msg in jMsg
+    toJsonMsg msg = case toJSON msg of
+      Object jMsg -> jMsg
+      value       -> error $ "unexpected non-object: " ++ show value
 
 ----------------------------------------
 
 -- | Check that login credentials are specified properly.
 --
 -- @since 0.10.0.0
-checkElasticSearchLogin :: ElasticSearchConfig -> IO ()
-checkElasticSearchLogin ElasticSearchConfig{..} =
-    when (isJust esLogin
-          && not esLoginInsecure
-          && not ("https:" `T.isPrefixOf` esServer)) $
-      error $ "ElasticSearch: insecure login: "
-        <> "Attempting to send login credentials over an insecure connection. "
-        <> "Set esLoginInsecure = True to disable this check."
+checkElasticSearchLogin :: MonadIO m => ElasticSearchConfig -> m ()
+checkElasticSearchLogin ElasticSearchConfig{..} = liftIO $ do
+  when (isJust esLogin
+        && not esLoginInsecure
+        && not ("https:" `T.isPrefixOf` esServer)) $
+    error $ "ElasticSearch: insecure login: "
+      <> "Attempting to send login credentials over an insecure connection. "
+      <> "Set esLoginInsecure = True to disable this check."
 
 -- | Check that we can connect to the ES server.
 --
 -- @since 0.10.0.0
-checkElasticSearchConnection :: ElasticSearchConfig -> IO (Either HttpException ())
-checkElasticSearchConnection esConf =
+checkElasticSearchConnection :: MonadIO m => ElasticSearchConfig -> m (Either HttpException ())
+checkElasticSearchConnection esConf = liftIO $ do
   fmap (const ()) <$> (serverInfo =<< mkEsEnv esConf)
diff --git a/src/Log/Backend/ElasticSearch/Internal.hs b/src/Log/Backend/ElasticSearch/Internal.hs
--- a/src/Log/Backend/ElasticSearch/Internal.hs
+++ b/src/Log/Backend/ElasticSearch/Internal.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveGeneric #-}
 module Log.Backend.ElasticSearch.Internal
   ( ElasticSearchConfig(..)
@@ -20,18 +21,19 @@
   , isSuccess
   ) where
 
-import Control.Applicative
 import Control.Exception
 import Control.Monad
 import Data.Aeson
 import Data.Ix (inRange)
 import Data.Maybe
-import Data.Semigroup
 import GHC.Generics (Generic)
 import Network.HTTP.Client
 import Network.HTTP.Types
+#if OPENSSL
+import Network.HTTP.Client.OpenSSL (newOpenSSLManager, withOpenSSL)
+#else
 import Network.HTTP.Client.TLS (tlsManagerSettings)
-import Prelude
+#endif
 import qualified Data.ByteString.Builder as BSB
 import qualified Data.ByteString.Lazy.Char8 as BSL
 import qualified Data.Text as T
@@ -203,7 +205,11 @@
 
 mkEsEnv :: ElasticSearchConfig -> IO EsEnv
 mkEsEnv ElasticSearchConfig{..} = do
+#if OPENSSL
+  envManager <- withOpenSSL newOpenSSLManager
+#else
   envManager <- newManager tlsManagerSettings
+#endif
   let envServer = esServer
       envRequestHook = maybe id mkAuthHook esLogin
   pure EsEnv{..}
diff --git a/src/Log/Backend/ElasticSearch/Lens.hs b/src/Log/Backend/ElasticSearch/Lens.hs
--- a/src/Log/Backend/ElasticSearch/Lens.hs
+++ b/src/Log/Backend/ElasticSearch/Lens.hs
@@ -13,7 +13,6 @@
   , I.withElasticSearchLogger
   ) where
 
-import Prelude
 import qualified Data.Text as T
 import qualified Log.Backend.ElasticSearch as I
 
