To avoid creating and destroying the DB pool and only set up the DB once, you need to use withSqliteConn in your main function on the outside and then transform each property to use that connection, like in this code:

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase| Person name String age Int Maybe deriving Show Eq |] type SqlT m = SqlPersistT (NoLoggingT (ResourceT m)) prop_insert_person :: PropertyM (SqlT IO) () prop_insert_person = do personName <- pick arbitrary personAge <- pick arbitrary let person = Person personName personAge -- This assertion will fail right now on the second iteration -- since I have not implemented the cleanup code numEntries <- run $ count ([] :: [Filter Person]) assert (numEntries == 0) personId <- run $ insert person result <- run $ get personId assert (result == Just person) main :: IO () main = runNoLoggingT $ withSqliteConn ":memory:" $ \connection -> lift $ do let -- Run a SqlT action using our connection runSql :: SqlT IO a -> IO a runSql = flip runSqlPersistM connection runSqlProperty :: SqlT IO Property -> Property runSqlProperty action = ioProperty . runSql $ do prop <- action liftIO $ putStrLn "

DB reset code (per test) goes here

" return prop quickCheckSql :: PropertyM (SqlT IO) () -> IO () quickCheckSql = quickCheck . monadic runSqlProperty -- Initial DB setup code runSql $ runMigration migrateAll -- Test as many quickcheck properties as you like quickCheckSql prop_insert_person

The full code including imports and extensions can be found in this gist.

Note that I did not implement the functionality to clean the database between tests, as I do not know how to do that in general with persistent, you will have to implement that yourself (replace the placeholder cleanup action that just prints a message right now).

You should also not need instances for MonadCatch / MonadThrow for PropertyM . Instead, you should catch in the NwApp monad. So instead of this:

let test = do run a ... run b test `catch` \exc -> ...

you should use the following code instead: