diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@
 ```
 
 
-# Universally Unique Lexicographically Sortable Identifier
+## Universally Unique Lexicographically Sortable Identifier
 
 UUID can be suboptimal for many uses-cases because:
 
@@ -46,6 +46,19 @@
 [Douglas Crockford's base 32]: https://www.crockford.com/base32.html
 
 
+## Known Issues
+
+- No monotonicity guarantees
+    ([official spec](
+      https://github.com/ulid/spec?tab=readme-ov-file#monotonicity))
+- Lexicographically sorted based on the random component
+    if timestamps are the same.
+    This causes the sort order to be non-deterministic
+    for ULIDs with the same timestamp,
+    but is necessary to avoid [incorrect `Map` and `Set` behavior](
+      https://github.com/haskell-github-trust/ulid/issues/15#issuecomment-2426847267).
+
+
 ## Usage
 
 A simple usage example:
@@ -72,7 +85,7 @@
 
 Example:
 
-````haskell
+```haskell
 module Main where
 
 import Data.ULID
@@ -83,21 +96,18 @@
 
 main :: IO ()
 main = do
-  -- This default instantiation may not be sufficiently secure.
-  -- See the docs at
-  -- hackage.haskell.org/package/crypto-api-0.13.2/docs/Crypto-Random.html
   g <- (CR.newGenIO :: IO CR.SystemRandom)
 
   -- Generate timestamp from current time
   t <- TS.getULIDTimeStamp
 
   let ulid3 = case UR.mkCryptoULIDRandom g of
-          Left err        -> error $ show err
-          -- use g2, …, to continue generating secure ULIDs
-          Right (rnd, g2) -> ULID t rnd
+        Left err        -> error $ show err
+        -- Use g2, …, to continue generating secure ULIDs
+        Right (rnd, g2) -> ULID t rnd
 
   print ulid3
-````
+```
 
 
 ## Test Suite
diff --git a/src/Data/ULID.hs b/src/Data/ULID.hs
--- a/src/Data/ULID.hs
+++ b/src/Data/ULID.hs
@@ -42,7 +42,8 @@
 import           Data.Data
 import           Data.Hashable
 import           Data.Monoid           ((<>))
-import           Data.Text as T
+import           Data.Text             (Text)
+import qualified Data.Text             as T
 import           Data.Time.Clock.POSIX
 import           GHC.Generics
 import           System.IO.Unsafe
@@ -62,10 +63,7 @@
   { timeStamp :: !ULIDTimeStamp
   , random    :: !ULIDRandom
   }
-  deriving (Eq, Typeable, Data, Generic)
-
-instance Ord ULID where
-    compare (ULID ts1 _) (ULID ts2 _) = compare ts1 ts2
+  deriving (Eq, Ord, Typeable, Data, Generic)
 
 instance Show ULID where
     show (ULID ts bytes) = show ts ++ show bytes
diff --git a/src/Data/ULID/Random.hs b/src/Data/ULID/Random.hs
--- a/src/Data/ULID/Random.hs
+++ b/src/Data/ULID/Random.hs
@@ -29,7 +29,7 @@
 
 -- | Newtype wrapping a `ByteString`
 newtype ULIDRandom = ULIDRandom BS.ByteString
-    deriving (Eq, Typeable, Data, Generic)
+    deriving (Eq, Ord, Typeable, Data, Generic)
 
 instance Show ULIDRandom where
     show (ULIDRandom r) = T.unpack $ B32.encode 16 . roll . BS.unpack $ r
diff --git a/test/Data/ULIDSpec.hs b/test/Data/ULIDSpec.hs
--- a/test/Data/ULIDSpec.hs
+++ b/test/Data/ULIDSpec.hs
@@ -6,12 +6,14 @@
 import qualified Data.ByteString.Lazy as LBS
 import           Data.Char
 import           Data.Hashable
-import           Data.List            (nub, sort)
+import           Data.List            (nub, sort, sortOn)
 import qualified System.Random        as R
 
 import           Data.ULID
 
 import           Test.Hspec
+import Data.ULID.TimeStamp (getULIDTimeStamp)
+import Data.ULID.Random (getULIDRandom)
 
 
 spec :: Spec
@@ -34,6 +36,20 @@
         let l' = sort l
         l' `shouldBe` [show u1, show u2, show u3, show u4]
 
+        -- it should be lexicographically sortable even if the timestamps are the same
+        ts <- getULIDTimeStamp
+        ur1 <- getULIDRandom
+        ur2 <- getULIDRandom
+        ur3 <- getULIDRandom
+        ur4 <- getULIDRandom
+
+        let u5 = ULID ts ur1
+        let u6 = ULID ts ur2
+        let u7 = ULID ts ur3
+        let u8 = ULID ts ur4
+
+        sort [u5, u6, u7, u8] `shouldBe` sortOn show [u5, u6, u7, u8]
+
         -- make sure it works in internal representation too :)
         let ul = [u3, u2, u4, u1]
         let ul' = sort ul
@@ -57,7 +73,7 @@
   describe "ulid" $ do
     it "starts with 0 (at least for the foreseeable future)" $ do
         u1 <- getULID
-        head (show u1) `shouldBe` '0'
+        take 1 (show u1) `shouldBe` ['0']
 
     it "generates unique ulids in default configuration" $ do
         let ops = 1000
diff --git a/ulid.cabal b/ulid.cabal
--- a/ulid.cabal
+++ b/ulid.cabal
@@ -1,5 +1,6 @@
+cabal-version:       3.8
 name:                ulid
-version:             0.3.2.0
+version:             0.3.3.0
 synopsis:            Implementation of ULID - Universally Unique
                      Lexicographically Sortable Identifier
 description:         Implementation of Alizain Feerasta's ULID specification.
@@ -9,15 +10,13 @@
                      for better efficiency and readability
                      (5 bits per character).
 homepage:            https://github.com/ad-si/ulid
-license:             BSD3
+license:             BSD-3-Clause
 license-file:        LICENSE
-author:              Steve Kollmansberger
+author:              Steve Kollmansberger, Adrian Sieber
 maintainer:          ulid@ad-si.com
-copyright:           2017 Steve Kollmansberger
 category:            Data, Codec, Database
 build-type:          Simple
 extra-source-files:  README.md
-cabal-version:       >=1.10
 
 
 library
@@ -52,7 +51,6 @@
 
 
 test-suite ulid-test
-  type:                exitcode-stdio-1.0
   hs-source-dirs:      test
   main-is:             Spec.hs
   other-modules:       Data.ULID.Base32Spec
@@ -72,7 +70,6 @@
 
 
 benchmark ulid-bench
-  type:                exitcode-stdio-1.0
   hs-source-dirs:      bench
   main-is:             Main.hs
   build-depends:       base
