diff --git a/.api-breakage/allowlist-branch-fix-deprecations.txt b/.api-breakage/allowlist-branch-fix-deprecations.txt
deleted file mode 100644
index fb86138..0000000
--- a/.api-breakage/allowlist-branch-fix-deprecations.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-API breakage: func DatabaseConfigurationFactory.postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:encodingContext:decodingContext:sqlLogLevel:) has removed default argument from parameter 3
-API breakage: func DatabaseConfigurationFactory.postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:encodingContext:decodingContext:sqlLogLevel:) has removed default argument from parameter 4
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:sqlLogLevel:) has parameter 0 type change from Swift.String to PostgresKit.SQLPostgresConfiguration
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:sqlLogLevel:) has parameter 2 type change from Swift.String to NIOCore.TimeAmount
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:sqlLogLevel:) has parameter 3 type change from Swift.String to Logging.Logger.Level
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:sqlLogLevel:) has parameter 0 type change from Swift.String to PostgresKit.SQLPostgresConfiguration
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:sqlLogLevel:) has parameter 2 type change from Swift.String to NIOCore.TimeAmount
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:sqlLogLevel:) has parameter 3 type change from Swift.String to PostgresNIO.PostgresEncodingContext<some PostgresNIO.PostgresJSONEncoder>
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:sqlLogLevel:) has parameter 4 type change from Swift.String? to Logging.Logger.Level
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:decoder:sqlLogLevel:) has parameter 0 type change from Swift.String to PostgresKit.SQLPostgresConfiguration
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:decoder:sqlLogLevel:) has parameter 2 type change from Swift.String to NIOCore.TimeAmount
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:decoder:sqlLogLevel:) has parameter 3 type change from Swift.String to PostgresNIO.PostgresDecodingContext<some PostgresNIO.PostgresJSONDecoder>
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:decoder:sqlLogLevel:) has parameter 4 type change from Swift.String? to Logging.Logger.Level
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:sqlLogLevel:) has been renamed to func postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:sqlLogLevel:)
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:sqlLogLevel:) has been renamed to func postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:encodingContext:sqlLogLevel:)
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:decoder:sqlLogLevel:) has been renamed to func postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:decodingContext:sqlLogLevel:)
-API breakage: func DatabaseConfigurationFactory.postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:sqlLogLevel:) has been removed
-API breakage: func DatabaseConfigurationFactory.postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:decoder:sqlLogLevel:) has been removed
diff --git a/.api-breakage/allowlist-branch-update-for-new-pnio.txt b/.api-breakage/allowlist-branch-update-for-new-pnio.txt
deleted file mode 100644
index b99af90..0000000
--- a/.api-breakage/allowlist-branch-update-for-new-pnio.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-API breakage: func DatabaseConfigurationFactory.postgres(url:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:decoder:sqlLogLevel:) has removed default argument from parameter 3
-API breakage: func DatabaseConfigurationFactory.postgres(url:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:decoder:sqlLogLevel:) has removed default argument from parameter 4
-API breakage: func DatabaseConfigurationFactory.postgres(url:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:decoder:sqlLogLevel:) has removed default argument from parameter 3
-API breakage: func DatabaseConfigurationFactory.postgres(url:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:decoder:sqlLogLevel:) has removed default argument from parameter 4
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:decoder:sqlLogLevel:) has removed default argument from parameter 8
-API breakage: func DatabaseConfigurationFactory.postgres(hostname:port:username:password:database:tlsConfiguration:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:decoder:sqlLogLevel:) has removed default argument from parameter 9
-API breakage: func DatabaseConfigurationFactory.postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:decoder:sqlLogLevel:) has removed default argument from parameter 3
-API breakage: func DatabaseConfigurationFactory.postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:encoder:decoder:sqlLogLevel:) has removed default argument from parameter 4
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
deleted file mode 100644
index 849dbe1..0000000
--- a/.github/CONTRIBUTING.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# Contributing to Fluent's PostgreSQL Driver
-
-👋 Welcome to the Vapor team! 
-
-## Docker
-
-In order to build and test against Postgres, you will need a database running. The easiest way to do this is using Docker and the included `docker-compose.yml` file.
-
-If you have Docker installed on your computer, all you will need to do is:
-
-```sh
-docker-compose up
-```
-
-This will start the two databases required for running this package's unit tests.
-
-## Xcode
-
-To open the project in Xcode:
-
-- Clone the repo to your computer
-- Drag and drop the folder onto Xcode
-
-To test within Xcode, press `CMD+U`.
-
-## SPM
-
-To develop using SPM, open the code in your favorite code editor. Use the following commands from within the project's root folder to build and test.
-
-```sh
-swift build
-swift test
-```
-
-## SemVer
-
-Vapor follows [SemVer](https://semver.org). This means that any changes to the source code that can cause
-existing code to stop compiling _must_ wait until the next major version to be included. 
-
-Code that is only additive and will not break any existing code can be included in the next minor release.
-
-----------
-
-Join us on Discord if you have any questions: [vapor.team](http://vapor.team).
-
-&mdash; Thanks! 🙌
diff --git a/.github/workflows/api-docs.yml b/.github/workflows/api-docs.yml
index a7122a8..c6086d5 100644
--- a/.github/workflows/api-docs.yml
+++ b/.github/workflows/api-docs.yml
@@ -11,4 +11,4 @@ jobs:
      with:
        package_name: fluent-postgres-driver
        modules: FluentPostgresDriver
-       pathsToInvalidate: /fluentpostgresdriver
+       pathsToInvalidate: /fluentpostgresdriver/*
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 2b4aa7c..4af2166 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -12,9 +12,9 @@ env:
   POSTGRES_HOSTNAME: 'psql-a'
   POSTGRES_HOSTNAME_A: 'psql-a'
   POSTGRES_HOSTNAME_B: 'psql-b'
-  POSTGRES_DB: 'test_database'
-  POSTGRES_DB_A: 'test_database'
-  POSTGRES_DB_B: 'test_database'
+  POSTGRES_DB: 'test_database_a'
+  POSTGRES_DB_A: 'test_database_a'
+  POSTGRES_DB_B: 'test_database_b'
   POSTGRES_USER: 'test_username'
   POSTGRES_USER_A: 'test_username'
   POSTGRES_USER_B: 'test_username'
@@ -24,15 +24,17 @@ env:
 
 jobs:
   api-breakage:
-    if: ${{ !(github.event.pull_request.draft || false) }}
+    if: ${{ github.event_name == 'pull_request' && !(github.event.pull_request.draft || false) }}
     runs-on: ubuntu-latest
-    container: swift:5.8-jammy
+    container: swift:jammy
     steps:
-      - name: Check out package
-        uses: actions/checkout@v3
+      - name: Checkout
+        uses: actions/checkout@v4
         with: { 'fetch-depth': 0 }
-      - name: Run API breakage check action
-        uses: vapor/ci/.github/actions/ci-swift-check-api-breakage@reusable-workflows
+      - name: API breaking changes
+        run: |
+          git config --global --add safe.directory "${GITHUB_WORKSPACE}"
+          swift package diagnose-api-breaking-changes origin/main
 
   linux-all:
     if: ${{ !(github.event.pull_request.draft || false) }}
@@ -40,50 +42,46 @@ jobs:
       fail-fast: false
       matrix:
         include:
-          - {dbimage: 'postgres:11', dbauth: 'trust',         swiftver: 'swift:5.7-focal'}
-          - {dbimage: 'postgres:13', dbauth: 'md5',           swiftver: 'swift:5.7-jammy'}
-          - {dbimage: 'postgres:15', dbauth: 'scram-sha-256', swiftver: 'swift:5.8-jammy'}
-          - {dbimage: 'postgres:15', dbauth: 'scram-sha-256', swiftver: 'swiftlang/swift:nightly-5.9-jammy'}
-          - {dbimage: 'postgres:15', dbauth: 'scram-sha-256', swiftver: 'swiftlang/swift:nightly-main-jammy'}
-    container: ${{ matrix.swiftver }}
+          - postgres-image-a: 'postgres:13'
+            postgres-image-b: 'postgres:14'
+            postgres-auth: 'trust'
+            swift-image: 'swift:5.8-focal'
+          - postgres-image-a: 'postgres:15'
+            postgres-image-b: 'postgres:16'
+            postgres-auth: 'md5'
+            swift-image: 'swift:5.10-jammy'
+          - postgres-image-a: 'postgres:15'
+            postgres-image-b: 'postgres:16'
+            postgres-auth: 'scram-sha-256'
+            swift-image: 'swiftlang/swift:nightly-6.0-jammy'
+    container: ${{ matrix.swift-image }}
     runs-on: ubuntu-latest
     services:
       psql-a:
-        image: ${{ matrix.dbimage }}
+        image: ${{ matrix.postgres-image-a }}
         env:
           POSTGRES_USER: 'test_username'
-          POSTGRES_DB: 'test_database'
+          POSTGRES_DB: 'test_database_a'
           POSTGRES_PASSWORD: 'test_password'
-          POSTGRES_HOST_AUTH_METHOD: ${{ matrix.dbauth }}
-          POSTGRES_INITDB_ARGS: --auth-host=${{ matrix.dbauth }}
+          POSTGRES_HOST_AUTH_METHOD: ${{ matrix.postgres-auth }}
+          POSTGRES_INITDB_ARGS: --auth-host=${{ matrix.postgres-auth }}
       psql-b:
-        image: ${{ matrix.dbimage }}
+        image: ${{ matrix.postgres-image-b }}
         env:
           POSTGRES_USER: 'test_username'
-          POSTGRES_DB: 'test_database'
+          POSTGRES_DB: 'test_database_b'
           POSTGRES_PASSWORD: 'test_password'
-          POSTGRES_HOST_AUTH_METHOD: ${{ matrix.dbauth }}
-          POSTGRES_INITDB_ARGS: --auth-host=${{ matrix.dbauth }}
+          POSTGRES_HOST_AUTH_METHOD: ${{ matrix.postgres-auth }}
+          POSTGRES_INITDB_ARGS: --auth-host=${{ matrix.postgres-auth }}
     steps:
-      - name: Display versions
-        shell: bash
-        run: |
-          echo POSTGRES_VERSION='${{ matrix.dbimage }}' >> $GITHUB_ENV
-          echo POSTGRES_AUTH_METHOD='${{ matrix.dbauth }}' >> $GITHUB_ENV
-          if [[ '${{ contains(matrix.container, 'nightly') }}' == 'true' ]]; then
-            SWIFT_PLATFORM="$(source /etc/os-release && echo "${ID}${VERSION_ID}")" SWIFT_VERSION="$(cat /.swift_tag)"
-            printf 'SWIFT_PLATFORM=%s\nSWIFT_VERSION=%s\n' "${SWIFT_PLATFORM}" "${SWIFT_VERSION}" >>"${GITHUB_ENV}"
-          fi
-          printf 'OS:  %s\nTag: %s\nVersion:\n' "${SWIFT_PLATFORM}-${RUNNER_ARCH}" "${SWIFT_VERSION}" && swift --version
       - name: Check out package
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
       - name: Run all tests
         run: swift test --sanitize=thread --enable-code-coverage
       - name: Submit coverage report to Codecov.io
-        uses: vapor/swift-codecov-action@v0.2
+        uses: vapor/swift-codecov-action@v0.3
         with:
-          cc_env_vars: 'SWIFT_VERSION,SWIFT_PLATFORM,RUNNER_OS,RUNNER_ARCH,POSTGRES_VERSION,POSTGRES_AUTH_METHOD'
-          cc_fail_ci_if_error: false
+          codecov_token: ${{ secrets.CODECOV_TOKEN }}
 
   macos-all:
     if: ${{ !(github.event.pull_request.draft || false) }}
@@ -91,41 +89,34 @@ jobs:
       fail-fast: false
       matrix:
         include:
-          - dbimage: postgresql@14
-            dbauth: scram-sha-256
-            macos: macos-13
-            xcode: latest-stable
-    runs-on: ${{ matrix.macos }}
+          - macos-version: macos-13
+            xcode-version: '~14.3'
+          - macos-version: macos-14
+            xcode-version: latest
+    runs-on: ${{ matrix.macos-version }}
     env:
       LOG_LEVEL: debug
       POSTGRES_HOSTNAME: 127.0.0.1
       POSTGRES_HOSTNAME_A: 127.0.0.1
       POSTGRES_HOSTNAME_B: 127.0.0.1
-      POSTGRES_DB: 'test_database_a'
-      POSTGRES_DB_A: 'test_database_a'
-      POSTGRES_DB_B: 'test_database_b'
-      POSTGRES_USER: 'test_username_a'
-      POSTGRES_USER_A: 'test_username_a'
-      POSTGRES_USER_B: 'test_username_b'
     steps:
       - name: Select latest available Xcode
         uses: maxim-lobanov/setup-xcode@v1
         with:
-          xcode-version: ${{ matrix.xcode }}
+          xcode-version: ${{ matrix.xcode-version }}
       - name: Install Postgres, setup DB and auth, and wait for server start
         run: |
-          export PATH="$(brew --prefix)/opt/${{ matrix.dbimage }}/bin:$PATH" PGDATA=/tmp/vapor-postgres-test PGUSER=postgres
-          (brew unlink postgresql || true) && brew install ${{ matrix.dbimage }} && brew link --force ${{ matrix.dbimage }}
-          initdb --locale=C --auth-host ${{ matrix.dbauth }} --username=postgres --pwfile=<(echo postgres)
+          brew upgrade || true
+          export PATH="$(brew --prefix)/opt/postgresql@16/bin:$PATH" PGDATA=/tmp/vapor-postgres-test PGUSER="${POSTGRES_USER_A}"
+          (brew unlink postgresql@14 || true) && brew install postgresql@16 && brew link --force postgresql@16
+          initdb --locale=C --auth-host "scram-sha-256" -U "${POSTGRES_USER_A}" --pwfile=<(echo "${POSTGRES_PASSWORD_A}")
           pg_ctl start --wait
-          psql postgres <<<"CREATE ROLE $POSTGRES_USER_A LOGIN PASSWORD '$POSTGRES_PASSWORD_A';"
-          psql postgres <<<"CREATE ROLE $POSTGRES_USER_B LOGIN PASSWORD '$POSTGRES_PASSWORD_B';"
-          psql postgres <<<"CREATE DATABASE $POSTGRES_DB_A OWNER = $POSTGRES_USER_A;"
-          psql postgres <<<"CREATE DATABASE $POSTGRES_DB_B OWNER = $POSTGRES_USER_B;"
-          psql $POSTGRES_DB_A <<<"ALTER SCHEMA public OWNER TO $POSTGRES_USER_A;"
-          psql $POSTGRES_DB_B <<<"ALTER SCHEMA public OWNER TO $POSTGRES_USER_B;"
-        timeout-minutes: 2
+          PGPASSWORD="${POSTGRES_PASSWORD_A}" createdb -w -O "${POSTGRES_USER_A}" "${POSTGRES_DB_A}"
+          PGPASSWORD="${POSTGRES_PASSWORD_A}" createdb -w -O "${POSTGRES_USER_B}" "${POSTGRES_DB_B}"
+          PGPASSWORD="${POSTGRES_PASSWORD_A}" psql -w "${POSTGRES_DB_A}" <<<"ALTER SCHEMA public OWNER TO ${POSTGRES_USER_A};"
+          PGPASSWORD="${POSTGRES_PASSWORD_A}" psql -w "${POSTGRES_DB_B}" <<<"ALTER SCHEMA public OWNER TO ${POSTGRES_USER_B};"
+        timeout-minutes: 15
       - name: Checkout code
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
       - name: Run all tests
         run: swift test --sanitize=thread
diff --git a/Package.swift b/Package.swift
index 3dfaa0a..e827a9c 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version:5.7
+// swift-tools-version:5.8
 import PackageDescription
 
 let package = Package(
@@ -18,15 +18,30 @@ let package = Package(
         .package(url: "https://github.com/vapor/postgres-kit.git", from: "2.11.4"),
     ],
     targets: [
-        .target(name: "FluentPostgresDriver", dependencies: [
-            .product(name: "AsyncKit", package: "async-kit"),
-            .product(name: "FluentKit", package: "fluent-kit"),
-            .product(name: "FluentSQL", package: "fluent-kit"),
-            .product(name: "PostgresKit", package: "postgres-kit"),
-        ]),
-        .testTarget(name: "FluentPostgresDriverTests", dependencies: [
-            .product(name: "FluentBenchmark", package: "fluent-kit"),
-            .target(name: "FluentPostgresDriver"),
-        ]),
+        .target(
+            name: "FluentPostgresDriver",
+            dependencies: [
+                .product(name: "AsyncKit", package: "async-kit"),
+                .product(name: "FluentKit", package: "fluent-kit"),
+                .product(name: "FluentSQL", package: "fluent-kit"),
+                .product(name: "PostgresKit", package: "postgres-kit"),
+            ],
+            swiftSettings: swiftSettings
+        ),
+        .testTarget(
+            name: "FluentPostgresDriverTests",
+            dependencies: [
+                .product(name: "FluentBenchmark", package: "fluent-kit"),
+                .target(name: "FluentPostgresDriver"),
+            ],
+            swiftSettings: swiftSettings
+        ),
     ]
 )
+
+var swiftSettings: [SwiftSetting] { [
+    .enableUpcomingFeature("ConciseMagicFile"),
+    .enableUpcomingFeature("ForwardTrailingClosures"),
+    .enableUpcomingFeature("DisableOutwardActorInference"),
+    .enableExperimentalFeature("StrictConcurrency=complete"),
+] }
diff --git a/Package@swift-5.9.swift b/Package@swift-5.9.swift
new file mode 100644
index 0000000..68670a8
--- /dev/null
+++ b/Package@swift-5.9.swift
@@ -0,0 +1,48 @@
+// swift-tools-version:5.9
+import PackageDescription
+
+let package = Package(
+    name: "fluent-postgres-driver",
+    platforms: [
+        .macOS(.v10_15),
+        .iOS(.v13),
+        .watchOS(.v6),
+        .tvOS(.v13),
+    ],
+    products: [
+        .library(name: "FluentPostgresDriver", targets: ["FluentPostgresDriver"]),
+    ],
+    dependencies: [
+        .package(url: "https://github.com/vapor/async-kit.git", from: "1.17.0"),
+        .package(url: "https://github.com/vapor/fluent-kit.git", from: "1.43.0"),
+        .package(url: "https://github.com/vapor/postgres-kit.git", from: "2.11.4"),
+    ],
+    targets: [
+        .target(
+            name: "FluentPostgresDriver",
+            dependencies: [
+                .product(name: "AsyncKit", package: "async-kit"),
+                .product(name: "FluentKit", package: "fluent-kit"),
+                .product(name: "FluentSQL", package: "fluent-kit"),
+                .product(name: "PostgresKit", package: "postgres-kit"),
+            ],
+            swiftSettings: swiftSettings
+        ),
+        .testTarget(
+            name: "FluentPostgresDriverTests",
+            dependencies: [
+                .product(name: "FluentBenchmark", package: "fluent-kit"),
+                .target(name: "FluentPostgresDriver"),
+            ],
+            swiftSettings: swiftSettings
+        ),
+    ]
+)
+
+var swiftSettings: [SwiftSetting] { [
+    .enableUpcomingFeature("ExistentialAny"),
+    .enableUpcomingFeature("ConciseMagicFile"),
+    .enableUpcomingFeature("ForwardTrailingClosures"),
+    .enableUpcomingFeature("DisableOutwardActorInference"),
+    .enableExperimentalFeature("StrictConcurrency=complete"),
+] }
diff --git a/README.md b/README.md
index 8803fe2..76a07bb 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,35 @@
 <p align="center">
-    <img 
-        src="https://user-images.githubusercontent.com/1342803/59065097-ec656880-8879-11e9-9e80-2e393dc313c1.png" 
-        height="64" 
-        alt="FluentPostgresDriver"
-    >
-    <br>
-    <br>
-    <a href="https://docs.vapor.codes/4.0/">
-        <img src="http://img.shields.io/badge/read_the-docs-2196f3.svg" alt="Documentation">
-    </a>
-    <a href="https://discord.gg/vapor">
-        <img src="https://img.shields.io/discord/431917998102675485.svg" alt="Team Chat">
-    </a>
-    <a href="LICENSE">
-        <img src="http://img.shields.io/badge/license-MIT-brightgreen.svg" alt="MIT License">
-    </a>
-    <a href="https://github.com/vapor/fluent-postgres-driver/actions/workflows/test.yml">
-        <img src="https://github.com/vapor/fluent-postgres-driver/actions/workflows/test.yml/badge.svg?event=push" alt="Continuous Integration">
-    </a>
-    <a href="https://codecov.io/gh/vapor/fluent-postgres-driver">
-        <img src="https://codecov.io/gh/vapor/fluent-postgres-driver/branch/main/graph/badge.svg?token=PizqqlcRSJ" alt="Test Coverage">
-    </a>
-    <a href="https://swift.org">
-        <img src="http://img.shields.io/badge/swift-5.7-brightgreen.svg" alt="Swift 5.7">
-    </a>
+<picture>
+  <source media="(prefers-color-scheme: dark)" srcset="https://github.com/vapor/fluent-postgres-driver/assets/1130717/c2350b70-aaf1-43e1-ab79-86fc88ba8da4">
+  <source media="(prefers-color-scheme: light)" srcset="https://github.com/vapor/fluent-postgres-driver/assets/1130717/dfc94dc2-281b-4e54-be86-549813496373">
+  <img src="https://github.com/vapor/fluent-postgres-driver/assets/1130717/dfc94dc2-281b-4e54-be86-549813496373" height="96" alt="FluentPostgresDriver">
+</picture> 
+<br>
+<br>
+<a href="https://docs.vapor.codes/4.0/"><img src="https://design.vapor.codes/images/readthedocs.svg" alt="Documentation"></a>
+<a href="https://discord.gg/vapor"><img src="https://design.vapor.codes/images/discordchat.svg" alt="Team Chat"></a>
+<a href="LICENSE"><img src="https://design.vapor.codes/images/mitlicense.svg" alt="MIT License"></a>
+<a href="https://github.com/vapor/fluent-postgres-driver/actions/workflows/test.yml"><img src="https://img.shields.io/github/actions/workflow/status/vapor/fluent-postgres-driver/test.yml?event=push&style=plastic&logo=github&label=tests&logoColor=%23ccc" alt="Continuous Integration"></a>
+<a href="https://codecov.io/github/vapor/fluent-postgres-driver"><img src="https://img.shields.io/codecov/c/github/vapor/fluent-postgres-driver?style=plastic&logo=codecov&label=codecov"></a>
+<a href="https://swift.org"><img src="https://design.vapor.codes/images/swift58up.svg" alt="Swift 5.8+"></a>
 </p>
+
+<br>
+
+FluentPostgresDriver is a [FluentKit] driver for PostgreSQL clients. It provides support for using the Fluent ORM with PostgreSQL databases, and uses [PostgresKit] to provide [SQLKit] driver services, [PostgresNIO] to connect and communicate with the database server asynchronously, and [AsyncKit] to provide connection pooling.
+
+[FluentKit]: https://github.com/vapor/fluent-kit
+[SQLKit]: https://github.com/vapor/sql-kit
+[PostgresKit]: https://github.com/vapor/postgres-kit
+[PostgresNIO]: https://github.com/vapor/postgres-nio
+[AsyncKit]: https://github.com/vapor/async-kit
+
+### Usage
+
+Use the SPM string to easily include the dependendency in your `Package.swift` file:
+
+```swift
+.package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.0.0")
+```
+
+For additional information, see [the Fluent documentation](https://docs.vapor.codes/fluent/overview/).
diff --git a/Sources/FluentPostgresDriver/DatabaseID+PostgreSQL.swift b/Sources/FluentPostgresDriver/DatabaseID+PostgreSQL.swift
index fc8370e..d50397f 100644
--- a/Sources/FluentPostgresDriver/DatabaseID+PostgreSQL.swift
+++ b/Sources/FluentPostgresDriver/DatabaseID+PostgreSQL.swift
@@ -2,6 +2,6 @@ import FluentKit
 
 extension DatabaseID {
     public static var psql: DatabaseID {
-        return .init(string: "psql")
+        .init(string: "psql")
     }
 }
diff --git a/Sources/FluentPostgresDriver/Docs.docc/Resources/vapor-fluentpostgresdriver-logo.svg b/Sources/FluentPostgresDriver/Docs.docc/Resources/vapor-fluentpostgresdriver-logo.svg
new file mode 100644
index 0000000..4cc9947
--- /dev/null
+++ b/Sources/FluentPostgresDriver/Docs.docc/Resources/vapor-fluentpostgresdriver-logo.svg
@@ -0,0 +1,21 @@
+<svg viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg" id="technology">
+  <defs>
+  <style>
+    @media(prefers-color-scheme:dark){:root{--color-logo-shape:#000;--color-logo-base:#fff}}
+    body[data-color-scheme="dark"]{--color-logo-shape:#000;--color-logo-base:#fff}
+  </style>
+  <path id="d" d="M6,47l58-47,58,47-58,45z" />
+  <path id="s" d="M6,47v12l58,45v-12z" />
+  <path id="h" d="m61.7,22c-3-.1-6.6,2-6.2,5.6l2,12-13.3-2.5c-6-1.2-9.8,7.3-3.8,8.5l13.3,2.4-11.4,9.5c-5,4.3,1,9.9,6,5.7l11.4-9.5,1.9,12c.9,5.3,10.7,2.6,9.8-2.8l-1.9-11.9,13.3,2.4c5.9,1.2,9.7-7.3,3.8-8.4l-13.4-2.5,11.4-9.5c5.1-4.2-1-9.8-6-5.7l-11.4,9.5-1.9-12c-.3-1.9-1.8-2.8-3.6-2.8zm2.2,11.9c-.1.2,0,.3.4.3-.9.5-1.3.9-1,1.3,1,.8,2.9-.1,4,2.8.1.4.4-.5.5-1.6.2.2.4.6.3,1.2,0,0,.6-1.9.6-1.9,1.3,2.1-.8,3.2-1.6,4.5-2.3,3.8,2,6,2.7,5.9,1.5.5.2,1.3,1.6,1.8.2.2-.3.6-1.6,1,.1.3.3.4.4.3,2.3.6.3,1.2-.5,1.3-.4-.2-.7-.5-.9-1-.8-.7-1.8-1.5-3-2.2-.7.2-1.4.8-1.9,1.8.8.5,1.5,1.1,2,1.7,1.1.1,1.4.3,1,.7-.5.3-.9.6-1.4.8-.3.1-1-.5-2.2-1.5.6.7,1.1,1.5,1.5,2.4,2,0,.3,1.3.1,1.4-.5.4-.9.3-1.3-.1-.9-1.9-4.5-3.4-5.2-3.6.3.2.6,1.2.5,1.7-.1-.7-.5-1.3-.9-1.9-.3-.6-2.4-4,3.8-6.8,1.1-.4-3.2-.8.8-3.1,0-.6.9-1.4,2.8-2.3.6-1.8-1.5-2-2.5-2.8-.4-.3-.5-1.2.8-1.9,0,0,.1-.2.2-.2zm3.6,13.1c.4.5.8.8.9,1,.3-.3-.1-.7-.9-1z" />
+  </defs>
+  <use href="#s" fill="#9ee0ff"/>
+  <use href="#s" fill="#6bd0ff" y="12"/>
+  <use href="#s" fill="#38c0ff" y="24"/>
+  <g transform="matrix(-1 0 0 1 128 0)">
+    <use href="#s" fill="#f29eff"/>
+    <use href="#s" fill="#eb6bff" y="12"/>
+    <use href="#s" fill="#e438ff" y="24"/>
+  </g>
+  <use href="#d" style="fill:var(--color-logo-base,#000)"/>
+  <use href="#h" style="fill:var(--color-logo-shape,#fff)"/>
+</svg>
diff --git a/Sources/FluentPostgresDriver/Docs.docc/index.md b/Sources/FluentPostgresDriver/Docs.docc/index.md
index e6f927d..08593bc 100644
--- a/Sources/FluentPostgresDriver/Docs.docc/index.md
+++ b/Sources/FluentPostgresDriver/Docs.docc/index.md
@@ -1,3 +1,14 @@
 # ``FluentPostgresDriver``
 
-FluentPostgresDriver is a package to integrate PostgresNIO and and PostrgresKit with FluentKit to make it easy to use and write database operations in Swift.
\ No newline at end of file
+FluentPostgresDriver is a [FluentKit] driver for PostgreSQL clients.
+
+## Overview
+
+FluentPostgresDriver provides support for using the Fluent ORM with PostgresSQL databases. It uses [PostgresKit] to provide [SQLKit] driver services, [PostgresNIO] to connect and communicate with the database server asynchronously, and [AsyncKit] to provide connection pooling.
+
+[FluentKit]: https://github.com/vapor/fluent-kit
+[SQLKit]: https://github.com/vapor/sql-kit
+[PostgresKit]: https://github.com/vapor/postgres-kit
+[PostgresNIO]: https://github.com/vapor/postgres-nio
+[AsyncKit]: https://github.com/vapor/async-kit
+
diff --git a/Sources/FluentPostgresDriver/Docs.docc/theme-settings.json b/Sources/FluentPostgresDriver/Docs.docc/theme-settings.json
new file mode 100644
index 0000000..6f0b9d4
--- /dev/null
+++ b/Sources/FluentPostgresDriver/Docs.docc/theme-settings.json
@@ -0,0 +1,21 @@
+{
+  "theme": {
+    "aside": { "border-radius": "16px", "border-style": "double", "border-width": "3px" },
+    "border-radius": "0",
+    "button": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
+    "code":   { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
+    "color": {
+      "fluentpsqldriver": "#336791",
+      "documentation-intro-fill": "radial-gradient(circle at top, var(--color-fluentpsqldriver) 30%, #000 100%)",
+      "documentation-intro-accent": "var(--color-fluentpsqldriver)",
+      "logo-base":  { "dark": "#fff", "light": "#000" },
+      "logo-shape": { "dark": "#000", "light": "#fff" },
+      "fill":       { "dark": "#000", "light": "#fff" }
+    },
+    "icons": { "technology": "/fluentpostgresdriver/images/vapor-fluentpostgresdriver-logo.svg" }
+  },
+  "features": {
+    "quickNavigation": { "enable": true },
+    "i18n": { "enable": true }
+  }
+}
diff --git a/Sources/FluentPostgresDriver/Exports.swift b/Sources/FluentPostgresDriver/Exports.swift
index 8aee3c6..f33f24c 100644
--- a/Sources/FluentPostgresDriver/Exports.swift
+++ b/Sources/FluentPostgresDriver/Exports.swift
@@ -1,12 +1,2 @@
-#if swift(>=5.8)
-
 @_documentation(visibility: internal) @_exported import FluentKit
 @_documentation(visibility: internal) @_exported import PostgresKit
-
-#else
-
-@_exported import FluentKit
-@_exported import PostgresKit
-
-#endif
-
diff --git a/Sources/FluentPostgresDriver/FluentPostgresConfiguration.swift b/Sources/FluentPostgresDriver/FluentPostgresConfiguration.swift
index b7f835b..39c94d0 100644
--- a/Sources/FluentPostgresDriver/FluentPostgresConfiguration.swift
+++ b/Sources/FluentPostgresDriver/FluentPostgresConfiguration.swift
@@ -81,7 +81,9 @@ extension DatabaseConfigurationFactory {
         decodingContext: PostgresDecodingContext<some PostgresJSONDecoder>,
         sqlLogLevel: Logger.Level = .debug
     ) -> DatabaseConfigurationFactory {
-        .init {
+        let configuration = FakeSendable(wrappedValue: configuration)
+        
+        return .init {
             FluentPostgresConfiguration(
                 configuration: configuration,
                 maxConnectionsPerEventLoop: maxConnectionsPerEventLoop,
@@ -93,6 +95,8 @@ extension DatabaseConfigurationFactory {
     }
 }
 
+fileprivate struct FakeSendable<T>: @unchecked Sendable { let wrappedValue: T }
+
 /// We'd like to just default the context parameters of the "actual" method. Unfortunately, there are a few
 /// cases involving the UNIX domain socket initalizer where usage can resolve to either the new
 /// ``SQLPostgresConfiguration``-based method or the deprecated ``PostgresConfiguration``-based method, with no
@@ -166,7 +170,7 @@ extension DatabaseConfigurationFactory {
 /// The actual concrete configuration type produced by a configuration factory.
 struct FluentPostgresConfiguration<E: PostgresJSONEncoder, D: PostgresJSONDecoder>: DatabaseConfiguration {
     var middleware: [any AnyModelMiddleware] = []
-    let configuration: SQLPostgresConfiguration
+    fileprivate let configuration: FakeSendable<SQLPostgresConfiguration>
     let maxConnectionsPerEventLoop: Int
     let connectionPoolTimeout: TimeAmount
     let encodingContext: PostgresEncodingContext<E>
@@ -174,7 +178,7 @@ struct FluentPostgresConfiguration<E: PostgresJSONEncoder, D: PostgresJSONDecode
     let sqlLogLevel: Logger.Level
 
     func makeDriver(for databases: Databases) -> any DatabaseDriver {
-        let connectionSource = PostgresConnectionSource(sqlConfiguration: self.configuration)
+        let connectionSource = PostgresConnectionSource(sqlConfiguration: self.configuration.wrappedValue)
         let elgPool = EventLoopGroupConnectionPool(
             source: connectionSource,
             maxConnectionsPerEventLoop: self.maxConnectionsPerEventLoop,
diff --git a/Sources/FluentPostgresDriver/FluentPostgresDatabase.swift b/Sources/FluentPostgresDriver/FluentPostgresDatabase.swift
index 3ec68a7..91eac91 100644
--- a/Sources/FluentPostgresDriver/FluentPostgresDatabase.swift
+++ b/Sources/FluentPostgresDriver/FluentPostgresDatabase.swift
@@ -16,14 +16,14 @@ struct _FluentPostgresDatabase<E: PostgresJSONEncoder, D: PostgresJSONDecoder> {
 extension _FluentPostgresDatabase: Database {
     func execute(
         query: DatabaseQuery,
-        onOutput: @escaping (any DatabaseOutput) -> ()
+        onOutput: @escaping @Sendable (any DatabaseOutput) -> ()
     ) -> EventLoopFuture<Void> {
         var expression = SQLQueryConverter(delegate: PostgresConverterDelegate()).convert(query)
         
         /// For `.create` query actions, we want to return the generated IDs, unless the `customIDKey` is the
         /// empty string, which we use as a very hacky signal for "we don't implement this for composite IDs yet".
         if case .create = query.action, query.customIDKey != .some(.string("")) {
-            expression = PostgresReturningID(base: expression, idKey: query.customIDKey ?? .id)
+            expression = SQLKit.SQLList([expression, SQLReturning(.init((query.customIDKey ?? .id).description))], separator: SQLRaw(" "))
         }
         
         return self.execute(sql: expression, { onOutput($0.databaseOutput()) })
@@ -34,7 +34,7 @@ extension _FluentPostgresDatabase: Database {
 
         return self.execute(sql: expression,
             // N.B.: Don't fatalError() here; what're users supposed to do about it?
-            { self.logger.error("Unexpected row returned from schema query: \($0)") }
+            { self.logger.debug("Unexpected row returned from schema query: \($0)") }
         )
     }
 
@@ -44,7 +44,7 @@ extension _FluentPostgresDatabase: Database {
             return e.createCases.reduce(self.create(enum: e.name)) { $0.value($1) }.run()
         case .update:
             if !e.deleteCases.isEmpty {
-                self.logger.error("PostgreSQL does not support deleting enum cases.")
+                self.logger.debug("PostgreSQL does not support deleting enum cases.")
             }
             guard !e.createCases.isEmpty else {
                 return self.eventLoop.makeSucceededFuture(())
@@ -58,7 +58,7 @@ extension _FluentPostgresDatabase: Database {
         }
     }
 
-    func transaction<T>(_ closure: @escaping (any Database) -> EventLoopFuture<T>) -> EventLoopFuture<T> {
+    func transaction<T>(_ closure: @escaping @Sendable (any Database) -> EventLoopFuture<T>) -> EventLoopFuture<T> {
         guard !self.inTransaction else {
             return closure(self)
         }
@@ -70,8 +70,8 @@ extension _FluentPostgresDatabase: Database {
                     """)
             }
             return sqlConn.raw("BEGIN").run().flatMap {
-                return closure(conn).flatMap { result in
-                    sqlConn.raw("COMMIT").run().map { result }
+                closure(conn).flatMap { result in
+                    sqlConn.raw("COMMIT").run().and(value: result).map { $1 }
                 }.flatMapError { error in
                     sqlConn.raw("ROLLBACK").run().flatMapThrowing { throw error }
                 }
@@ -79,7 +79,7 @@ extension _FluentPostgresDatabase: Database {
         }
     }
     
-    func withConnection<T>(_ closure: @escaping (any Database) -> EventLoopFuture<T>) -> EventLoopFuture<T> {
+    func withConnection<T>(_ closure: @escaping @Sendable (any Database) -> EventLoopFuture<T>) -> EventLoopFuture<T> {
         self.withConnection { (underlying: any PostgresDatabase) in
             closure(_FluentPostgresDatabase(
                 database: underlying.sql(encodingContext: self.encodingContext, decodingContext: self.decodingContext, queryLogLevel: self.database.queryLogLevel),
@@ -111,9 +111,17 @@ extension _FluentPostgresDatabase: SQLDatabase {
     var dialect: any SQLDialect { self.database.dialect }
     var queryLogLevel: Logger.Level? { self.database.queryLogLevel }
     
-    func execute(sql query: any SQLExpression, _ onRow: @escaping (any SQLRow) -> ()) -> EventLoopFuture<Void> {
+    func execute(sql query: any SQLExpression, _ onRow: @escaping @Sendable (any SQLRow) -> ()) -> EventLoopFuture<Void> {
         self.database.execute(sql: query, onRow)
     }
+    
+    func execute(sql query: any SQLExpression, _ onRow: @escaping @Sendable (any SQLRow) -> ()) async throws {
+        try await self.database.execute(sql: query, onRow)
+    }
+    
+    func withSession<R>(_ closure: @escaping @Sendable (any SQLDatabase) async throws -> R) async throws -> R {
+        try await self.database.withSession(closure)
+    }
 }
 
 extension _FluentPostgresDatabase: PostgresDatabase {
@@ -132,15 +140,3 @@ extension _FluentPostgresDatabase: PostgresDatabase {
         return psqlDb.withConnection(closure)
     }
 }
-
-private struct PostgresReturningID: SQLExpression {
-    let base: any SQLExpression
-    let idKey: FieldKey
-
-    func serialize(to serializer: inout SQLSerializer) {
-        serializer.statement {
-            $0.append(self.base)
-            $0.append("RETURNING", SQLIdentifier(self.idKey.description))
-        }
-    }
-}
diff --git a/Sources/FluentPostgresDriver/FluentPostgresDriver.swift b/Sources/FluentPostgresDriver/FluentPostgresDriver.swift
index d7201ef..400ae5a 100644
--- a/Sources/FluentPostgresDriver/FluentPostgresDriver.swift
+++ b/Sources/FluentPostgresDriver/FluentPostgresDriver.swift
@@ -4,7 +4,8 @@ import Logging
 import FluentKit
 import PostgresKit
 
-struct _FluentPostgresDriver<E: PostgresJSONEncoder, D: PostgresJSONDecoder>: DatabaseDriver {
+/// Marked `@unchecked Sendable` to silence warning about `PostgresConnectionSource`
+struct _FluentPostgresDriver<E: PostgresJSONEncoder, D: PostgresJSONDecoder>: DatabaseDriver, @unchecked Sendable {
     let pool: EventLoopGroupConnectionPool<PostgresConnectionSource>
     let encodingContext: PostgresEncodingContext<E>
     let decodingContext: PostgresDecodingContext<D>
diff --git a/Sources/FluentPostgresDriver/PostgresError+Database.swift b/Sources/FluentPostgresDriver/PostgresError+Database.swift
index 68cc3ee..a214b6e 100644
--- a/Sources/FluentPostgresDriver/PostgresError+Database.swift
+++ b/Sources/FluentPostgresDriver/PostgresError+Database.swift
@@ -92,7 +92,7 @@ extension PSQLError: DatabaseError {
     
     public var isConnectionClosed: Bool {
         switch self.code {
-        case .connectionClosed: return true
+        case .serverClosedConnection, .clientClosedConnection: return true
         default: return false
         }
     }
diff --git a/Tests/FluentPostgresDriverTests/FluentPostgresDriverTests.swift b/Tests/FluentPostgresDriverTests/FluentPostgresDriverTests.swift
index a2f510e..2297391 100644
--- a/Tests/FluentPostgresDriverTests/FluentPostgresDriverTests.swift
+++ b/Tests/FluentPostgresDriverTests/FluentPostgresDriverTests.swift
@@ -6,11 +6,37 @@ import XCTest
 import PostgresKit
 import SQLKit
 
+func XCTAssertThrowsErrorAsync<T>(
+    _ expression: @autoclosure () async throws -> T,
+    _ message: @autoclosure () -> String = "",
+    file: StaticString = #filePath, line: UInt = #line,
+    _ callback: (any Error) -> Void = { _ in }
+) async {
+    do {
+        _ = try await expression()
+        XCTAssertThrowsError({}(), message(), file: file, line: line, callback)
+    } catch {
+        XCTAssertThrowsError(try { throw error }(), message(), file: file, line: line, callback)
+    }
+}
+
+func XCTAssertNoThrowAsync<T>(
+    _ expression: @autoclosure () async throws -> T,
+    _ message: @autoclosure () -> String = "",
+    file: StaticString = #filePath, line: UInt = #line
+) async {
+    do {
+        _ = try await expression()
+    } catch {
+        XCTAssertNoThrow(try { throw error }(), message(), file: file, line: line)
+    }
+}
+
 final class FluentPostgresDriverTests: XCTestCase {
-    //func testAll() throws { try self.benchmarker.testAll() }
     func testAggregate() throws { try self.benchmarker.testAggregate() }
     func testArray() throws { try self.benchmarker.testArray() }
     func testBatch() throws { try self.benchmarker.testBatch() }
+    func testChild() throws { try self.benchmarker.testChildren() }
     func testChildren() throws { try self.benchmarker.testChildren() }
     func testChunk() throws { try self.benchmarker.testChunk() }
     func testCodable() throws { try self.benchmarker.testCodable() }
@@ -40,84 +66,91 @@ final class FluentPostgresDriverTests: XCTestCase {
     func testTransaction() throws { try self.benchmarker.testTransaction() }
     func testUnique() throws { try self.benchmarker.testUnique() }
 
-    func testDatabaseError() throws {
-        let sql = (self.db as! any SQLDatabase)
-        do {
-            try sql.raw("asd").run().wait()
-        } catch let error as DatabaseError where error.isSyntaxError {
-            // PASS
-        } catch {
-            XCTFail("\(error)")
+    func testDatabaseError() async throws {
+        let sql1 = (self.db as! any SQLDatabase)
+        await XCTAssertThrowsErrorAsync(try await sql1.raw("asdf").run()) {
+            XCTAssertTrue(($0 as? any DatabaseError)?.isSyntaxError ?? false, "\(String(reflecting: $0))")
+            XCTAssertFalse(($0 as? any DatabaseError)?.isConstraintFailure ?? true, "\(String(reflecting: $0))")
+            XCTAssertFalse(($0 as? any DatabaseError)?.isConnectionClosed ?? true, "\(String(reflecting: $0))")
         }
-        do {
-            try sql.raw("CREATE TABLE foo (name TEXT UNIQUE)").run().wait()
-            try sql.raw("INSERT INTO foo (name) VALUES ('bar')").run().wait()
-            try sql.raw("INSERT INTO foo (name) VALUES ('bar')").run().wait()
-        } catch let error as DatabaseError where error.isConstraintFailure {
-            // pass
-        } catch {
-            XCTFail("\(error)")
+        
+        let sql2 = (self.dbs.database(.a, logger: .init(label: "test.fluent.a"), on: self.eventLoopGroup.any())!) as! any SQLDatabase
+        try await sql2.drop(table: "foo").ifExists().run()
+        try await sql2.create(table: "foo").column("name", type: .text, .unique).run()
+        try await sql2.insert(into: "foo").columns("name").values("bar").run()
+        await XCTAssertThrowsErrorAsync(try await sql2.insert(into: "foo").columns("name").values("bar").run()) {
+            XCTAssertTrue(($0 as? any DatabaseError)?.isConstraintFailure ?? false, "\(String(reflecting: $0))")
+            XCTAssertFalse(($0 as? any DatabaseError)?.isSyntaxError ?? true, "\(String(reflecting: $0))")
+            XCTAssertFalse(($0 as? any DatabaseError)?.isConnectionClosed ?? true, "\(String(reflecting: $0))")
         }
+        
+        // Disabled until we figure out why it hangs instead of throwing an error.
+        //let postgres = (self.dbs.database(.a, logger: .init(label: "test.fluent.a"), on: self.eventLoopGroup.any())!) as! any PostgresDatabase
+        //await XCTAssertThrowsErrorAsync(try await postgres.withConnection { conn in
+        //    conn.close().flatMap {
+        //        conn.sql().insert(into: "foo").columns("name").values("bar").run()
+        //    }
+        //}.get()) {
+        //    XCTAssertTrue(($0 as? any DatabaseError)?.isConnectionClosed ?? false, "\(String(reflecting: $0))")
+        //    XCTAssertFalse(($0 as? any DatabaseError)?.isSyntaxError ?? true, "\(String(reflecting: $0))")
+        //    XCTAssertFalse(($0 as? any DatabaseError)?.isConstraintFailure ?? true, "\(String(reflecting: $0))")
+        //}
     }
     
-    func testBlob() throws {
-        struct CreateFoo: Migration {
-            func prepare(on database: any Database) -> EventLoopFuture<Void> {
-                database.schema("foos")
+    func testBlob() async throws {
+        struct CreateFoo: AsyncMigration {
+            func prepare(on database: any Database) async throws {
+                try await database.schema("foos")
                     .field("id", .int, .identifier(auto: true))
                     .field("data", .data, .required)
                     .create()
             }
 
-            func revert(on database: any Database) -> EventLoopFuture<Void> {
-                database.schema("foos").delete()
+            func revert(on database: any Database) async throws {
+                try await database.schema("foos").delete()
             }
         }
 
-        try CreateFoo().prepare(on: self.db).wait()
-        try CreateFoo().revert(on: self.db).wait()
+        try await CreateFoo().prepare(on: self.db)
+        try await CreateFoo().revert(on: self.db)
     }
 
-    func testSaveModelWithBool() throws {
-        final class Organization: Model {
+    func testSaveModelWithBool() async throws {
+        final class Organization: Model, @unchecked Sendable {
             static let schema = "orgs"
 
-            @ID(custom: "id", generatedBy: .database)
-            var id: Int?
+            @ID(custom: "id", generatedBy: .database) var id: Int?
+            @Field(key: "disabled") var disabled: Bool
 
-            @Field(key: "disabled")
-            var disabled: Bool
-
-            init() { }
+            init() {}
         }
 
-        struct CreateOrganization: Migration {
-            func prepare(on database: any Database) -> EventLoopFuture<Void> {
-                database.schema("orgs")
+        struct CreateOrganization: AsyncMigration {
+            func prepare(on database: any Database) async throws {
+                try await database.schema("orgs")
                     .field("id", .int, .identifier(auto: true))
                     .field("disabled", .bool, .required)
                     .create()
             }
 
-            func revert(on database: any Database) -> EventLoopFuture<Void> {
-                database.schema("orgs").delete()
+            func revert(on database: any Database) async throws {
+                try await database.schema("orgs").delete()
             }
         }
 
-        try CreateOrganization().prepare(on: self.db).wait()
-        defer {
-            try! CreateOrganization().revert(on: self.db).wait()
+        try await CreateOrganization().prepare(on: self.db)
+        do {
+            let new = Organization()
+            new.disabled = false
+            try await new.save(on: self.db)
+        } catch {
+            try? await CreateOrganization().revert(on: self.db)
+            throw error
         }
-
-        let new = Organization()
-        new.disabled = false
-        try new.save(on: self.db).wait()
+        try await CreateOrganization().revert(on: self.db)
     }
 
-    func testCustomJSON() throws {
-        try EventMigration().prepare(on: self.db).wait()
-        defer { try! EventMigration().revert(on: self.db).wait() }
-
+    func testCustomJSON() async throws {
         let jsonEncoder = JSONEncoder()
         jsonEncoder.dateEncodingStrategy = .iso8601
         let jsonDecoder = JSONDecoder()
@@ -133,60 +166,73 @@ final class FluentPostgresDriverTests: XCTestCase {
             on: self.eventLoopGroup.any()
         )!
 
-        let date = Date()
-        let event = Event()
-        event.id = 1
-        event.metadata = Metadata(createdAt: date)
-        try event.save(on: db).wait()
-
-        let rows = try EventStringlyTyped.query(on: db).filter(\.$id == 1).all().wait()
-        let expected = ISO8601DateFormatter().string(from: date)
-        XCTAssertEqual(rows[0].metadata["createdAt"], expected)
+        try await EventMigration().prepare(on: db)
+        do {
+            let date = Date()
+            let event = Event()
+            event.id = 1
+            event.metadata = Metadata(createdAt: date)
+            try await event.save(on: db)
+
+            let rows = try await EventStringlyTyped.query(on: db).filter(\.$id == 1).all()
+            let expected = ISO8601DateFormatter().string(from: date)
+            XCTAssertEqual(rows[0].metadata["createdAt"], expected)
+        } catch {
+            try? await EventMigration().revert(on: db)
+            throw error
+        }
+        try await EventMigration().revert(on: db)
     }
 
-    func testEnumAddingMultipleCases() throws {
-        try EnumMigration().prepare(on: self.db).wait()
-        try EventWithFooMigration().prepare(on: self.db).wait()
-
-        let event = EventWithFoo()
-        event.foobar = .foo
-        try event.save(on: self.db).wait()
-
-        XCTAssertNoThrow(try EnumAddMultipleCasesMigration().prepare(on: self.db).wait())
-
-        event.foobar = .baz
-        XCTAssertNoThrow(try event.update(on: self.db).wait())
-        event.foobar = .qux
-        XCTAssertNoThrow(try event.update(on: self.db).wait())
-
-        XCTAssertNoThrow(try EnumAddMultipleCasesMigration().revert(on: self.db).wait())
-        try! EventWithFooMigration().revert(on: self.db).wait()
-        try! EnumMigration().revert(on: self.db).wait()
+    func testEnumAddingMultipleCases() async throws {
+        try await EnumMigration().prepare(on: self.db)
+        do {
+            try await EventWithFooMigration().prepare(on: self.db)
+            do {
+                let event = EventWithFoo()
+                event.foobar = .foo
+                try await event.save(on: self.db)
+
+                await XCTAssertNoThrowAsync(try await EnumAddMultipleCasesMigration().prepare(on: self.db))
+
+                event.foobar = .baz
+                await XCTAssertNoThrowAsync(try await event.update(on: self.db))
+                event.foobar = .qux
+                await XCTAssertNoThrowAsync(try await event.update(on: self.db))
+
+                await XCTAssertNoThrowAsync(try await EnumAddMultipleCasesMigration().revert(on: self.db))
+            } catch {
+                try? await EventWithFooMigration().revert(on: self.db)
+                throw error
+            }
+        } catch {
+            try? await EnumMigration().revert(on: self.db)
+            throw error
+        }
     }
     
-    func testEncodingArrayOfModels() throws {
-        final class Elem: Model, ExpressibleByIntegerLiteral {
+    func testEncodingArrayOfModels() async throws {
+        final class Elem: Model, ExpressibleByIntegerLiteral, @unchecked Sendable {
             static let schema = ""
             @ID(custom: .id) var id: Int?
             init() {}; init(integerLiteral l: Int) { self.id = l }
         }
-        final class Seq: Model, ExpressibleByNilLiteral, ExpressibleByArrayLiteral {
+        final class Seq: Model, ExpressibleByNilLiteral, ExpressibleByArrayLiteral, @unchecked Sendable {
             static let schema = "seqs"
             @ID(custom: .id) var id: Int?; @OptionalField(key: "list") var list: [Elem]?
             init() {}; init(nilLiteral: ()) { self.list = nil }; init(arrayLiteral el: Elem...) { self.list = el }
         }
         do {
-            try self.db.schema(Seq.schema).field(.id, .int, .identifier(auto: true)).field("list", .sql(embed: "JSONB[]")).create().wait()
-            defer { try! db.schema(Seq.schema).delete().wait() }
+            try await self.db.schema(Seq.schema).field(.id, .int, .identifier(auto: true)).field("list", .sql(embed: "JSONB[]")).create()
             
             let s1: Seq = [1, 2], s2: Seq = nil; try [s1, s2].forEach { try $0.create(on: self.db).wait() }
             
             // Make sure it went into the DB as "array of jsonb" rather than as "array of one jsonb containing array" or such.
-            let raws = try (self.db as! SQLDatabase).raw("SELECT array_to_json(list)::text t FROM seqs").all().wait().map { try $0.decode(column: "t", as: String?.self) }
+            let raws = try await (self.db as! any SQLDatabase).raw("SELECT array_to_json(list)::text t FROM seqs").all().map { try $0.decode(column: "t", as: String?.self) }
             XCTAssertEqual(raws, [#"[{"id": 1},{"id": 2}]"#, nil])
             
             // Make sure it round-trips through Fluent.
-            let seqs = try Seq.query(on: self.db).all().wait()
+            let seqs = try await Seq.query(on: self.db).all()
             
             XCTAssertEqual(seqs.count, 2)
             XCTAssertEqual(seqs.dropFirst(0).first?.id, s1.id)
@@ -196,47 +242,40 @@ final class FluentPostgresDriverTests: XCTestCase {
         } catch let error {
             XCTFail("caught error: \(String(reflecting: error))")
         }
+        try await db.schema(Seq.schema).delete()
     }
 
     
-    var benchmarker: FluentBenchmarker {
-        return .init(databases: self.dbs)
-    }
-    var eventLoopGroup: (any EventLoopGroup)!
-    var threadPool: NIOThreadPool!
+    var benchmarker: FluentBenchmarker { .init(databases: self.dbs) }
+    var eventLoopGroup: any EventLoopGroup { MultiThreadedEventLoopGroup.singleton }
+    var threadPool: NIOThreadPool { NIOThreadPool.singleton }
     var dbs: Databases!
-    var db: any Database {
-        self.benchmarker.database
-    }
-    var postgres: any PostgresDatabase {
-        self.db as! any PostgresDatabase
-    }
+    var db: (any Database)!
+    var postgres: any PostgresDatabase { self.db as! any PostgresDatabase }
     
-    override func setUpWithError() throws {
-        try super.setUpWithError()
+    override func setUp() async throws {
+        try await super.setUp()
         
         XCTAssert(isLoggingConfigured)
-        self.eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: Swift.min(System.coreCount, 2))
-        self.threadPool = NIOThreadPool(numberOfThreads: 1)
-        self.dbs = Databases(threadPool: threadPool, on: self.eventLoopGroup)
+        self.dbs = Databases(threadPool: self.threadPool, on: self.eventLoopGroup)
 
         self.dbs.use(.testPostgres(subconfig: "A"), as: .a)
         self.dbs.use(.testPostgres(subconfig: "B"), as: .b)
 
-        let a = self.dbs.database(.a, logger: Logger(label: "test.fluent.a"), on: self.eventLoopGroup.any())
-        _ = try (a as! any PostgresDatabase).query("drop schema public cascade").wait()
-        _ = try (a as! any PostgresDatabase).query("create schema public").wait()
+        let a = self.dbs.database(.a, logger: .init(label: "test.fluent.a"), on: self.eventLoopGroup.any())
+        _ = try await (a as! any PostgresDatabase).query("drop schema public cascade").get()
+        _ = try await (a as! any PostgresDatabase).query("create schema public").get()
 
-        let b = self.dbs.database(.b, logger: Logger(label: "test.fluent.b"), on: self.eventLoopGroup.any())
-        _ = try (b as! any PostgresDatabase).query("drop schema public cascade").wait()
-        _ = try (b as! any PostgresDatabase).query("create schema public").wait()
-    }
+        let b = self.dbs.database(.b, logger: .init(label: "test.fluent.b"), on: self.eventLoopGroup.any())
+        _ = try await (b as! any PostgresDatabase).query("drop schema public cascade").get()
+        _ = try await (b as! any PostgresDatabase).query("create schema public").get()
+
+        self.db = a
+     }
 
-    override func tearDownWithError() throws {
+    override func tearDown() async throws {
         self.dbs.shutdown()
-        try self.threadPool.syncShutdownGracefully()
-        try self.eventLoopGroup.syncShutdownGracefully()
-        try super.tearDownWithError()
+        try await super.tearDown()
     }
 }
 
@@ -265,15 +304,11 @@ extension DatabaseID {
     static let b = DatabaseID(string: "b")
 }
 
-func env(_ name: String) -> String? {
-    ProcessInfo.processInfo.environment[name]
-}
-
 struct Metadata: Codable {
     let createdAt: Date
 }
 
-final class Event: Model {
+final class Event: Model, @unchecked Sendable {
     static let schema = "events"
 
     @ID(custom: "id", generatedBy: .database)
@@ -283,7 +318,7 @@ final class Event: Model {
     var metadata: Metadata
 }
 
-final class EventStringlyTyped: Model {
+final class EventStringlyTyped: Model, @unchecked Sendable {
     static let schema = "events"
 
     @ID(custom: "id", generatedBy: .database)
@@ -293,20 +328,20 @@ final class EventStringlyTyped: Model {
     var metadata: [String: String]
 }
 
-struct EventMigration: Migration {
-    func prepare(on database: any Database) -> EventLoopFuture<Void> {
-        database.schema(Event.schema)
+struct EventMigration: AsyncMigration {
+    func prepare(on database: any Database) async throws {
+        try await database.schema(Event.schema)
             .field("id", .int, .identifier(auto: true))
             .field("metadata", .json, .required)
             .create()
     }
 
-    func revert(on database: any Database) -> EventLoopFuture<Void> {
-        database.schema(Event.schema).delete()
+    func revert(on database: any Database) async throws {
+        try await database.schema(Event.schema).delete()
     }
 }
 
-final class EventWithFoo: Model {
+final class EventWithFoo: Model, @unchecked Sendable {
     static let schema = "foobar_events"
 
     @ID
@@ -324,58 +359,57 @@ enum Foobar: String, Codable {
     case qux
 }
 
-struct EventWithFooMigration: Migration {
-    func prepare(on database: any Database) -> EventLoopFuture<Void> {
-        database.enum(Foobar.schema).read()
-            .flatMap { foobar in
-                database.schema(EventWithFoo.schema)
-                    .id()
-                    .field("foo", foobar, .required)
-                    .create()
-            }
+struct EventWithFooMigration: AsyncMigration {
+    func prepare(on database: any Database) async throws {
+        let foobar = try await database.enum(Foobar.schema).read()
+        try await database.schema(EventWithFoo.schema)
+            .id()
+            .field("foo", foobar, .required)
+            .create()
     }
 
-    func revert(on database: any Database) -> EventLoopFuture<Void> {
-        database.schema(EventWithFoo.schema).delete()
+    func revert(on database: any Database) async throws {
+        try await database.schema(EventWithFoo.schema).delete()
     }
 }
 
-struct EnumMigration: Migration {
-    func prepare(on database: any Database) -> EventLoopFuture<Void> {
-        database.enum(Foobar.schema)
+struct EnumMigration: AsyncMigration {
+    func prepare(on database: any Database) async throws {
+        _ = try await database.enum(Foobar.schema)
             .case("foo")
             .case("bar")
             .create()
-            .transform(to: ())
     }
 
-    func revert(on database: any Database) -> EventLoopFuture<Void> {
-        database.enum(Foobar.schema).delete()
+    func revert(on database: any Database) async throws {
+        try await database.enum(Foobar.schema).delete()
     }
 }
 
-struct EnumAddMultipleCasesMigration: Migration {
-    func prepare(on database: any Database) -> EventLoopFuture<Void> {
-        database.enum(Foobar.schema)
+struct EnumAddMultipleCasesMigration: AsyncMigration {
+    func prepare(on database: any Database) async throws {
+        _ = try await database.enum(Foobar.schema)
             .case("baz")
             .case("qux")
             .update()
-            .transform(to: ())
     }
 
-    func revert(on database: any Database) -> EventLoopFuture<Void> {
-        database.enum(Foobar.schema)
+    func revert(on database: any Database) async throws {
+        _ = try await database.enum(Foobar.schema)
             .deleteCase("baz")
             .deleteCase("qux")
             .update()
-            .transform(to: ())
     }
 }
 
+func env(_ name: String) -> String? {
+    ProcessInfo.processInfo.environment[name]
+}
+
 let isLoggingConfigured: Bool = {
     LoggingSystem.bootstrap { label in
         var handler = StreamLogHandler.standardOutput(label: label)
-        handler.logLevel = env("LOG_LEVEL").flatMap { Logger.Level(rawValue: $0) } ?? .info
+        handler.logLevel = env("LOG_LEVEL").flatMap { .init(rawValue: $0) } ?? .info
         return handler
     }
     return true
diff --git a/Tests/FluentPostgresDriverTests/FluentPostgresTransactionControlTests.swift b/Tests/FluentPostgresDriverTests/FluentPostgresTransactionControlTests.swift
index 727f1e3..fa8f784 100644
--- a/Tests/FluentPostgresDriverTests/FluentPostgresTransactionControlTests.swift
+++ b/Tests/FluentPostgresDriverTests/FluentPostgresTransactionControlTests.swift
@@ -6,9 +6,9 @@ import XCTest
 import PostgresKit
 
 final class FluentPostgresTransactionControlTests: XCTestCase {
-    func testRollback() throws {
+    func testRollback() async throws {
         do {
-            try self.db.withConnection { db -> EventLoopFuture<Void> in
+            try await self.db.withConnection { db -> EventLoopFuture<Void> in
                 (db as! any TransactionControlDatabase).beginTransaction().flatMap { () -> EventLoopFuture<Void> in
                     let todo1 = Todo(title: "Test")
                     return todo1.save(on: db)
@@ -22,7 +22,7 @@ final class FluentPostgresTransactionControlTests: XCTestCase {
                                 .flatMap { db.eventLoop.makeFailedFuture(e) }
                         }
                 }
-            }.wait()
+            }.get()
             XCTFail("Expected error but none was thrown")
         } catch let error where String(reflecting: error).contains("sqlState: 23505") {
             // ignore
@@ -30,41 +30,37 @@ final class FluentPostgresTransactionControlTests: XCTestCase {
             XCTFail("Expected SQL state 23505 but got \(String(reflecting: error))")
         }
 
-        let count2 = try Todo.query(on: self.db).count().wait()
+        let count2 = try await Todo.query(on: self.db).count()
         XCTAssertEqual(count2, 0)
     }
     
-    var eventLoopGroup: (any EventLoopGroup)!
-    var threadPool: NIOThreadPool!
+    var eventLoopGroup: any EventLoopGroup { MultiThreadedEventLoopGroup.singleton }
+    var threadPool: NIOThreadPool { NIOThreadPool.singleton }
     var dbs: Databases!
     var db: (any Database)!
     
-    override func setUpWithError() throws {
-        try super.setUpWithError()
+    override func setUp() async throws {
+        try await super.setUp()
         
         XCTAssert(isLoggingConfigured)
-        self.eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: Swift.min(System.coreCount, 2))
-        self.threadPool = NIOThreadPool(numberOfThreads: 1)
-        self.dbs = Databases(threadPool: threadPool, on: self.eventLoopGroup)
+        self.dbs = Databases(threadPool: self.threadPool, on: self.eventLoopGroup)
 
         self.dbs.use(.testPostgres(subconfig: "A"), as: .a)
 
         self.db = self.dbs.database(.a, logger: Logger(label: "test.fluent.a"), on: self.eventLoopGroup.any())
-        _ = try (self.db as! PostgresDatabase).query("drop schema public cascade").wait()
-        _ = try (self.db as! PostgresDatabase).query("create schema public").wait()
+        _ = try await (self.db as! any PostgresDatabase).query("drop schema public cascade").get()
+        _ = try await (self.db as! any PostgresDatabase).query("create schema public").get()
         
-        try CreateTodo().prepare(on: self.db).wait()
+        try await CreateTodo().prepare(on: self.db)
     }
 
-    override func tearDownWithError() throws {
-        try CreateTodo().revert(on: self.db).wait()
+    override func tearDown() async throws {
+        try await CreateTodo().revert(on: self.db)
         self.dbs.shutdown()
-        try self.threadPool.syncShutdownGracefully()
-        try self.eventLoopGroup.syncShutdownGracefully()
-        try super.tearDownWithError()
+        try await super.tearDown()
     }
     
-    final class Todo: Model {
+    final class Todo: Model, @unchecked Sendable {
         static let schema = "todos"
 
         @ID
@@ -77,17 +73,17 @@ final class FluentPostgresTransactionControlTests: XCTestCase {
         init(title: String) { self.title = title; id = nil }
     }
     
-    struct CreateTodo: Migration {
-        func prepare(on database: any Database) -> EventLoopFuture<Void> {
-            database.schema("todos")
+    struct CreateTodo: AsyncMigration {
+        func prepare(on database: any Database) async throws {
+            try await database.schema("todos")
                 .id()
                 .field("title", .string, .required)
                 .unique(on: "title")
                 .create()
         }
 
-        func revert(on database: any Database) -> EventLoopFuture<Void> {
-            database.schema("todos").delete()
+        func revert(on database: any Database) async throws {
+            try await database.schema("todos").delete()
         }
     }
 }
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100644
index 13b7a21..0000000
--- a/docker-compose.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-version: '3'
-
-services:
-  a:
-    image: postgres
-    environment:
-      POSTGRES_USER: vapor_username
-      POSTGRES_DB: vapor_database
-      POSTGRES_PASSWORD: vapor_password
-    ports:
-      - 5432:5432
-  b:
-    image: postgres
-    environment:
-      POSTGRES_USER: vapor_username
-      POSTGRES_DB: vapor_database
-      POSTGRES_PASSWORD: vapor_password
-    ports:
-      - 5433:5432