diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history of `resource-registry`
 
+## 0.3.0.0 - 2026-07-13
+
+* Removed `transferRegistry`.
+
 ## 0.2.1.0 - 2026-03-04
 
 * Define `impossibleToNotTransfer` for fundamental resource allocation in
diff --git a/resource-registry.cabal b/resource-registry.cabal
--- a/resource-registry.cabal
+++ b/resource-registry.cabal
@@ -1,6 +1,6 @@
 cabal-version: 3.0
 name: resource-registry
-version: 0.2.1.0
+version: 0.3.0.0
 synopsis: Track allocated resources
 description:
   When the scope of a @bracket@ doesn't enclose all uses of the resource, a
@@ -21,7 +21,7 @@
 category: Control
 build-type: Simple
 bug-reports: https://github.com/IntersectMBO/io-classes-extra/issues
-tested-with: ghc ==9.6 || ==9.8 || ==9.10 || ==9.12
+tested-with: ghc ==9.6 || ==9.8 || ==9.10 || ==9.12 || ==9.14
 extra-doc-files:
   CHANGELOG.md
   README.md
@@ -35,7 +35,7 @@
   type: git
   location: https://github.com/IntersectMBO/io-classes-extra
   subdir: resource-registry
-  tag: resource-registry-0.2.0.0
+  tag: resource-registry-0.3.0.0
 
 common warnings
   ghc-options:
@@ -57,7 +57,7 @@
     base >=4.14 && <4.23,
     bimap ^>=0.5,
     containers >=0.6.7 && <0.9,
-    io-classes:{io-classes, strict-stm} ^>=1.8 || ^>=1.9,
+    io-classes:{io-classes, strict-stm} >=1.8 && <1.11,
     mtl ^>=2.3,
     nothunks ^>=0.2 || ^>=0.3,
 
@@ -78,12 +78,12 @@
     Test.Util.ToExpr
 
   build-depends:
-    QuickCheck,
     base,
     containers,
     generics-sop,
     io-classes:{io-classes, si-timers, strict-mvar, strict-stm},
     mtl,
+    QuickCheck,
     quickcheck-state-machine:no-vendored-treediff,
     resource-registry,
     tasty,
diff --git a/src/Control/ResourceRegistry.hs b/src/Control/ResourceRegistry.hs
--- a/src/Control/ResourceRegistry.hs
+++ b/src/Control/ResourceRegistry.hs
@@ -264,7 +264,6 @@
   , modifyWithTempRegistry
   , runInnerWithTempRegistry
   , runWithTempRegistry
-  , transferRegistry
   , impossibleToNotTransfer
 
     -- * Unsafe combinators primarily for testing
@@ -480,7 +479,7 @@
 
 -- | Allocate key for new resource
 allocKey :: State (RegistryState m) (Either PrettyCallStack ResourceId)
-allocKey = unlessClosed $ unsafeAllocKey
+allocKey = unlessClosed unsafeAllocKey
 
 unsafeAllocKey :: State (RegistryState m) ResourceId
 unsafeAllocKey = do
@@ -488,10 +487,6 @@
   modify $ \st -> st{registryNextKey = succ nextKey}
   return nextKey
 
--- | Allocate multiple keys for resources
-allocNKeys :: Int -> State (RegistryState m) (Either PrettyCallStack [ResourceId])
-allocNKeys n = unlessClosed $ replicateM n $ unsafeAllocKey
-
 -- | Insert new resource
 insertResource ::
   ResourceId ->
@@ -1225,7 +1220,7 @@
   (MonadMask m, MonadSTM m, MonadThread m, HasCallStack) =>
   ResourceRegistry m ->
   m ()
-releaseAll rr = releaseAllBy (\_ -> unlessClosed $ gets getYoungestToOldest) rr
+releaseAll = releaseAllBy (\_ -> unlessClosed $ gets getYoungestToOldest)
 
 -- | This is to 'releaseAll' what 'unsafeRelease' is to 'release': we do not
 -- insist that this funciton is called from a thread that is known to the
@@ -1612,50 +1607,3 @@
   NoThunks (Bimap k v)
   where
   wNoThunks ctxt = noThunksInKeysAndValues ctxt . Bimap.toList
-
--- | Move all the resources from the origin registry to the destination
--- registry and return the list of allocated 'ResourceKey's.
---
--- Transferring individual resources between registries is risky because a
--- later resource in the origin registry might depend on a resource that we are
--- trying to transfer. However, transferring whole registries is fine.
-transferRegistry ::
-  (MonadSTM m, MonadMask m, MonadThread m, HasCallStack) =>
-  ResourceRegistry m ->
-  ResourceRegistry m ->
-  m [ResourceKey m]
-transferRegistry fromReg toReg = do
-  context <- captureContext
-
-  -- The calling thread is known to the origin registry
-  ensureKnownThread fromReg context
-
-  -- Alloc all the needed keys
-  mKeys <- updateState toReg . allocNKeys =<< countResources fromReg
-
-  case mKeys of
-    -- If the destination registry is closed, throw
-    Left closed -> throwRegistryClosed toReg context closed
-    Right keys -> mask_ $ do
-      -- Get the resources out of the origin registry and empty it
-      regState <- atomically $ swapTVar (registryState fromReg) initState
-
-      forM_
-        ( zip keys $
-            Map.elems (registryResources regState)
-        )
-        ( \(k, res) -> do
-            -- Insert the resources into the new registry
-            inserted <- updateState toReg (insertResource k res)
-
-            case inserted of
-              -- If the destination registry is closed, throw
-              Left closed -> do
-                let Release rel = resourceRelease res
-                void rel
-                throwRegistryClosed toReg context closed
-              Right () ->
-                pure ()
-        )
-
-      pure $ map (ResourceKey toReg) keys
