diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Change log
 
+## 0.3.0.0
+
+* Removed `TxErrorType` and change the `errorType` field on `TxException` to `errcode`.
+
 ## 0.2.0.0
 
 * Changed the `TxM` encoding from a plain newtype-over-IO to a reader.
diff --git a/package.yaml b/package.yaml
--- a/package.yaml
+++ b/package.yaml
@@ -1,5 +1,5 @@
 name:                postgresql-tx
-version:             0.2.0.0
+version:             0.3.0.0
 github:              "simspace/postgresql-tx"
 license:             BSD3
 license-file:        LICENSE.md
diff --git a/postgresql-tx.cabal b/postgresql-tx.cabal
--- a/postgresql-tx.cabal
+++ b/postgresql-tx.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 6502ef6d385db187552d31216c423233d2ea504b31a19ce4f273aa8aeb6773c0
+-- hash: 66842eb2c8ecef116494783907dbe032bf945a4e2439098e2d7a5f5da57296da
 
 name:           postgresql-tx
-version:        0.2.0.0
+version:        0.3.0.0
 synopsis:       A safe transaction monad for use with various PostgreSQL Haskell libraries.
 description:    Please see the README on GitHub at <https://github.com/simspace/postgresql-tx#readme>
 category:       Database
diff --git a/src/Database/PostgreSQL/Tx.hs b/src/Database/PostgreSQL/Tx.hs
--- a/src/Database/PostgreSQL/Tx.hs
+++ b/src/Database/PostgreSQL/Tx.hs
@@ -15,7 +15,6 @@
   , throwExceptionTx
   , mapExceptionTx
   , TxException(..)
-  , TxErrorType(..)
   , shouldRetryTx
   ) where
 
diff --git a/src/Database/PostgreSQL/Tx/Internal.hs b/src/Database/PostgreSQL/Tx/Internal.hs
--- a/src/Database/PostgreSQL/Tx/Internal.hs
+++ b/src/Database/PostgreSQL/Tx/Internal.hs
@@ -9,6 +9,7 @@
 {-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE TypeFamilies #-}
@@ -160,43 +161,58 @@
         Nothing -> throwIO ex
         Just ex' -> throwIO ex'
 
+-- | Unified exception type thrown from the database.
+--
+-- Each database backend may throw different types of exceptions.
+-- As a user of @postgresql-tx@, ideally we should be able to
+-- detect exceptions from the database without needing to catch
+-- the database backend's exception type.
+--
+-- The 'errcode' field allows us to introspect the postgresql
+-- @errcode@; see https://www.postgresql.org/docs/current/errcodes-appendix.html
+--
+-- If you need to inspect the exact exception thrown by a database
+-- backend, use the 'cause' field.
 data TxException = TxException
-  { errorType :: TxErrorType
+  { errcode :: Maybe String
   , cause :: SomeException
   } deriving stock (Show)
 
 instance Exception TxException
 
-data TxErrorType =
-    TxSerializationFailure
-  | TxDeadlockDetected
-  | TxOtherError (Maybe String) -- ^ PostgreSQL @errcode@, if applicable.
-    deriving stock (Show, Eq)
+-- | PostgreSQL @errcode@ for @serialization_failure@.
+errcode'serialization_failure :: String
+errcode'serialization_failure = "40001"
 
-shouldRetryTx :: TxException -> Bool
-shouldRetryTx e =
-  errorType e `elem`
-    [ TxSerializationFailure
-    , TxDeadlockDetected
-    ]
+-- | PostgreSQL @errcode@ for @deadlock_detected@.
+errcode'deadlock_detected :: String
+errcode'deadlock_detected = "40P01"
 
-fromSqlState :: Maybe String -> TxErrorType
-fromSqlState = \case
-  Just "40001" -> TxSerializationFailure
-  Just "40P01" -> TxDeadlockDetected
-  sqlState -> TxOtherError sqlState
+-- | Checks if the 'errcode' of a 'TxException' matches the supplied predicate.
+-- If the 'errcode' is 'Nothing', returns 'False'.
+hasErrcode :: (String -> Bool) -> TxException -> Bool
+hasErrcode p TxException { errcode } = any p errcode
 
+-- | Useful as a predicate to indicate when to retry transactions which are
+-- run at isolation level @serializable@
+shouldRetryTx :: TxException -> Bool
+shouldRetryTx =
+  hasErrcode
+    (`elem`
+      [ errcode'serialization_failure
+      , errcode'deadlock_detected
+      ])
+
+-- | Construct a 'TxException' from an @errcode@ accessing function
+-- and the 'cause' exception.
+--
+-- Note that this function should only be used by libraries
+-- which are implementing a database backend for @postgresql-tx@.
 unsafeMkTxException
   :: (Exception e) => (e -> Maybe String) -> e -> TxException
-unsafeMkTxException f = unsafeMkTxException' (fromSqlState . f)
-
-unsafeMkTxException'
-  :: (Exception e)
-  => (e -> TxErrorType)
-  -> e -> TxException
-unsafeMkTxException' f e =
+unsafeMkTxException f e =
   TxException
-    { errorType = f e
+    { errcode = f e
     , cause = toException e
     }
 
