diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,24 @@
 # Changelog
 
+## 1.1.0.0 — 2026-07-13
+
+Major release: this set removes a public error constructor and changes callback exception
+behavior.
+
+### Breaking changes
+
+- Removed `MigratedDatabaseCallbackCleanupFailed`; a successful callback value now wins
+  when only its connection release fails.
+- Asynchronous callback exceptions now propagate after cleanup instead of being returned as
+  `MigratedDatabaseCallbackFailed`.
+
+### Fixes and behavior changes
+
+- Acquire the callback connection inside the same masked bracket that runs the callback and
+  releases the connection, closing the interruption leak window.
+- Preserve both exceptions in `MigratedDatabaseCallbackAndCleanupFailed` when a synchronous
+  callback failure and connection-release failure occur together.
+
 ## 1.0.0.0 — 2026-07-10
 
 - Initial stable release of the `ephemeral-pg` helper with fresh Hasql callback connections
diff --git a/pg-migrate-test-support.cabal b/pg-migrate-test-support.cabal
--- a/pg-migrate-test-support.cabal
+++ b/pg-migrate-test-support.cabal
@@ -1,6 +1,6 @@
 cabal-version:   3.8
 name:            pg-migrate-test-support
-version:         1.0.0.0
+version:         1.1.0.0
 synopsis:        Ephemeral PostgreSQL helpers for pg-migrate tests
 category:        Database
 maintainer:      nadeem@gmail.com
@@ -31,7 +31,7 @@
     , base          >=4.20 && <4.22
     , ephemeral-pg  >=0.2  && <0.3
     , hasql         >=1.10 && <1.11
-    , pg-migrate    >=1.0  && <1.1
+    , pg-migrate    >=1.1  && <1.2
 
 test-suite pg-migrate-test-support-test
   import:         common
diff --git a/src/Database/PostgreSQL/Migrate/Test.hs b/src/Database/PostgreSQL/Migrate/Test.hs
--- a/src/Database/PostgreSQL/Migrate/Test.hs
+++ b/src/Database/PostgreSQL/Migrate/Test.hs
@@ -1,7 +1,7 @@
 -- | Test-only ephemeral PostgreSQL lifecycle. A validated plan is applied before a fresh
 -- Hasql connection is bracketed around the caller's assertion callback.
 module Database.PostgreSQL.Migrate.Test
-  ( -- | Structured startup, migration, callback, and cleanup failures.
+  ( -- | Structured startup, migration, callback, and callback-plus-cleanup failures.
     MigratedDatabaseError (..),
     -- | Start a database, apply a plan with default runner options, and run a callback.
     withMigratedDatabase,
@@ -17,15 +17,17 @@
 import Database.PostgreSQL.Migrate
 import EphemeralPg qualified
 import Hasql.Connection qualified as Connection
+import Hasql.Connection.Settings qualified as Settings
 import Hasql.Errors qualified as Errors
 
--- | Structured failures from the ephemeral database, migration, callback, or cleanup stages.
+-- | Structured failures from the ephemeral database, migration, callback, or a callback
+-- failure accompanied by a connection-release failure. A release failure after a
+-- successful callback does not replace its value.
 data MigratedDatabaseError
   = MigratedDatabaseStartupFailed !EphemeralPg.StartError
   | MigratedDatabaseMigrationFailed !MigrationError
   | MigratedDatabaseCallbackAcquisitionFailed !Errors.ConnectionError
   | MigratedDatabaseCallbackFailed !SomeException
-  | MigratedDatabaseCallbackCleanupFailed !SomeException
   | MigratedDatabaseCallbackAndCleanupFailed !SomeException !SomeException
   deriving stock (Show)
 
@@ -45,6 +47,7 @@
 withMigratedDatabaseOptions = withMigratedDatabaseConfig EphemeralPg.defaultConfig
 
 -- | Fully configurable variant accepting both ephemeral database and migration options.
+-- Asynchronous callback exceptions are rethrown after releasing the callback connection.
 withMigratedDatabaseConfig ::
   EphemeralPg.Config ->
   RunOptions ->
@@ -58,26 +61,30 @@
       migrated <- runMigrationPlan options settings plan
       case migrated of
         Left migrationError -> pure (Left (MigratedDatabaseMigrationFailed migrationError))
-        Right _ -> do
-          acquired <- Connection.acquire settings
-          case acquired of
-            Left connectionError -> pure (Left (MigratedDatabaseCallbackAcquisitionFailed connectionError))
-            Right connection -> runCallback connection callback
+        Right _ -> runCallback settings callback
   pure $ case started of
     Left startError -> Left (MigratedDatabaseStartupFailed startError)
     Right result -> result
 
 runCallback ::
-  Connection.Connection ->
+  Settings.Settings ->
   (Connection.Connection -> IO value) ->
   IO (Either MigratedDatabaseError value)
-runCallback connection callback =
+runCallback settings callback =
   Exception.mask $ \restore -> do
-    callbackResult <- Exception.try (restore (callback connection))
-    cleanupResult <- Exception.try (Connection.release connection)
-    pure $ case (callbackResult, cleanupResult) of
-      (Right value, Right ()) -> Right value
-      (Left callbackError, Right ()) -> Left (MigratedDatabaseCallbackFailed callbackError)
-      (Right _, Left cleanupError) -> Left (MigratedDatabaseCallbackCleanupFailed cleanupError)
-      (Left callbackError, Left cleanupError) ->
-        Left (MigratedDatabaseCallbackAndCleanupFailed callbackError cleanupError)
+    acquired <- Connection.acquire settings
+    case acquired of
+      Left connectionError -> pure (Left (MigratedDatabaseCallbackAcquisitionFailed connectionError))
+      Right connection -> do
+        callbackResult <- Exception.try @SomeException (restore (callback connection))
+        cleanupResult <- Exception.try @SomeException (Connection.release connection)
+        case callbackResult of
+          Left callbackError
+            | Just _ <- Exception.fromException @Exception.SomeAsyncException callbackError ->
+                Exception.throwIO callbackError
+          _ ->
+            pure $ case (callbackResult, cleanupResult) of
+              (Right value, _) -> Right value
+              (Left callbackError, Right ()) -> Left (MigratedDatabaseCallbackFailed callbackError)
+              (Left callbackError, Left cleanupError) ->
+                Left (MigratedDatabaseCallbackAndCleanupFailed callbackError cleanupError)
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -24,6 +24,7 @@
         [ testCase "plan is migrated before a fresh callback connection" testMigratedDatabase,
           testCase "migration failures are structurally distinct" testMigrationFailure,
           testCase "callback failures are structurally distinct" testCallbackFailure,
+          testCase "asynchronous callback exceptions propagate" testAsyncCallbackException,
           testCase "startup failures are structurally distinct" testStartupFailure
         ]
     )
@@ -51,6 +52,16 @@
   case result of
     Left MigratedDatabaseCallbackFailed {} -> pure ()
     other -> assertFailure ("expected callback failure, received: " <> show other)
+
+testAsyncCallbackException :: Assertion
+testAsyncCallbackException = do
+  result <-
+    Exception.try @Exception.AsyncException
+      (withMigratedDatabase fixturePlan (const (Exception.throwIO Exception.UserInterrupt) :: Connection.Connection -> IO ()))
+  case result of
+    Left Exception.UserInterrupt -> pure ()
+    Left exception -> assertFailure ("expected UserInterrupt, received: " <> show exception)
+    Right callbackResult -> assertFailure ("expected propagated async exception, received: " <> show callbackResult)
 
 testStartupFailure :: Assertion
 testStartupFailure = do
